UNPKG

14.3 kBJavaScriptView Raw
1/* Enterprise Web Application Stack */import{join}from'path';import{parseJSON,Application,dumpYAML,ApplicationSettings,conf}from'agentstack';/*! *****************************************************************************
2Copyright (c) Microsoft Corporation. All rights reserved.
3Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4this file except in compliance with the License. You may obtain a copy of the
5License at http://www.apache.org/licenses/LICENSE-2.0
6
7THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
8KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
9WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
10MERCHANTABLITY OR NON-INFRINGEMENT.
11
12See the Apache Version 2.0 License for specific language governing permissions
13and limitations under the License.
14***************************************************************************** */function __decorate(a,b,e,f){var g,d=arguments.length,c=3>d?b:null===f?f=Object.getOwnPropertyDescriptor(b,e):f;if('object'==typeof Reflect&&'function'==typeof Reflect.decorate)c=Reflect.decorate(a,b,e,f);else for(var h=a.length-1;0<=h;h--)(g=a[h])&&(c=(3>d?g(c):3<d?g(b,e,c):g(b,e))||c);return 3<d&&c&&Object.defineProperty(b,e,c),c}function __metadata(a,b){if('object'==typeof Reflect&&'function'==typeof Reflect.metadata)return Reflect.metadata(a,b)}function __awaiter(a,b,c,d){return new(c||(c=Promise))(function(e,f){function g(a){try{i(d.next(a))}catch(a){f(a)}}function h(a){try{i(d['throw'](a))}catch(a){f(a)}}function i(a){a.done?e(a.value):new c(function(b){b(a.value)}).then(g,h)}i((d=d.apply(a,b||[])).next())})}const fe=require('fs-extra');function resolveStandaloneServerEntryFile(a){return a.file('src/bin/standalone.ts').path}function resolveStandaloneServerConfigFile(a){if(fe.pathExistsSync(join(a.settings.HOME_DIR,'src/bin/tsconfig.json')))return join(a.settings.HOME_DIR,'src/bin/tsconfig.json');if(fe.pathExistsSync(join(a.settings.HOME_DIR,'src/tsconfig.json')))return join(a.settings.HOME_DIR,'src/tsconfig.json');if(fe.pathExistsSync(join(a.settings.HOME_DIR,'tsconfig.json')))return join(a.settings.HOME_DIR,'tsconfig.json');throw new Error('unable to find tsconfig.json for standalone server')}function resolveWebApplicationBrowserEntryFile(a){return a.file('src/webapp/main.browser.ts').path}function resolveWebApplicationBrowserConfigFile(a){return a.file('src/webapp/tsconfig.json').path}function GenerateWebpackConfig(a){return __awaiter(this,void 0,void 0,function*(){const b='build'===a.settings.ENV,c=require('webpack'),d=require('extract-text-webpack-plugin'),e={fileLoader:'file-loader',cssLoader:b?'css-loader?minimize':'css-loader',stylusLoader:'stylus-loader',vueLoader:'vue-loader',vueStyleLoader:'vue-style-loader',tsLoader:'ts-loader',babelLoader:'babel-loader'},f=b?d.extract({use:e.cssLoader,fallback:e.vueStyleLoader}):[e.vueStyleLoader,e.cssLoader],g=b?d.extract({use:[e.cssLoader,e.stylusLoader],fallback:e.vueStyleLoader}):[e.vueStyleLoader,e.cssLoader,e.stylusLoader],h=[];b&&h.push({loader:e.babelLoader,options:{presets:['minify']}}),h.push({loader:e.tsLoader,options:{transpileOnly:!0,configFile:resolveWebApplicationBrowserConfigFile(a),appendTsSuffixTo:[/\.vue$/]}});const i={test:/\.vue$/,loader:e.vueLoader,options:{preserveWhitespace:!1,loaders:{css:f,stylus:g}}},j={devtool:!b&&'#cheap-module-source-map',output:{filename:'[name].[hash].js',chunkFilename:'[device].[hash].js'},resolve:{extensions:['.ts','.vue','.js','.css'],alias:{"@":a.settings.PUBLIC_DIR,"~":a.settings.HOME_DIR}},performance:{maxEntrypointSize:3e5,hints:!!b&&'warning'},module:{noParse:/es6-promise\.js$/,rules:[i,{test:/\.tsx?$/,loader:h,exclude:/node_modules/},{test:/\.css$/,use:f},{test:/\.styl$/,use:g},{test:/\.stylus$/,use:g},{test:/\.(png|jpe?g|gif|svg)(\?.*)?$/,loader:e.fileLoader,options:{name:'img/[name].[hash:7].[ext]'}},{test:/\.(woff2?|eot|ttf|otf)(\?.*)?$/,loader:e.fileLoader,options:{name:'fonts/[name].[hash:7].[ext]'}}]},plugins:[]};if(a.settings.PUBLIC_URL&&(j.output.publicPath=a.settings.PUBLIC_URL+'/'),b){j.output.path=join(a.settings.RELEASE_DIR,'public');const b=require('autoprefixer');i.options.postcss=[b({browsers:['last 3 versions']})],j.plugins.push(new c.optimize.ModuleConcatenationPlugin),j.plugins.push(new d({filename:'common.[chunkhash].css'}))}else j.output.publicPath||(j.output.publicPath='/');return j})}const KnownPackages=[['vue','Vue','dist/vue.min.js'],['vuex','Vuex','dist/vuex.min.js'],['vue-router','VueRouter','dist/vue-router.min.js'],['element-ui','ELEMENT','lib/index.js'],['axios','axios','dist/axios.min.js']];function GenerateWebappBrowserConfig(a){return __awaiter(this,void 0,void 0,function*(){const b=yield GenerateWebpackConfig(a),c=require('webpack'),d=require('webpack-merge'),e='build'===a.settings.ENV,f=d(b,{entry:{app:[resolveWebApplicationBrowserEntryFile(a)]},output:{libraryTarget:'umd'},resolve:{extensions:['.ts','.vue','.js','.css']},plugins:[new c.DefinePlugin({"process.env.NODE_ENV":JSON.stringify(e?'production':'development'),"process.env.VUE_ENV":'"client"'}),new c.optimize.CommonsChunkPlugin({name:'vendor',minChunks:function(a){return /node_modules/.test(a.context)&&!/\.css$/.test(a.req)}}),new c.optimize.CommonsChunkPlugin({name:'manifest'})]}),g=require('html-webpack-plugin');if(f.plugins.push(new g({title:`${a.settings.TITLE||a.settings.NAME}`,filename:'index.html',template:join(a.settings.PUBLIC_DIR,'index.template.html'),inject:!0,cache:!0,xhtml:!0,minify:{removeComments:!0,collapseWhitespace:!0,removeAttributeQuotes:!0},chunksSortMode:'dependency'})),a.settings.USE_EXTERNAL_CDN){const b=parseJSON(a.file('package.json')),c=Object.keys(b.dependencies||{}),d=Object.keys(b.devDependencies||{}),e=[];for(const b of KnownPackages)if(0<=c.indexOf(b[0])||0<=d.indexOf(b[0])){const c=parseJSON(a.file(join('node_modules',b[0],'package.json')));b.push(c.version),e.push(b)}const g=e.map((a)=>({module:a[0],entry:`https://unpkg.com/${a[0]}@${a[3]}/${a[2]}`,global:a[1]}));if(console.log('found externals',g.map((a)=>a.module)),g.length){const a=require('html-webpack-externals-plugin');f.plugins.push(new a({externals:g,hash:!0,outputPath:'vendor'}))}}const h=require('sw-precache-webpack-plugin');if(f.plugins.push(new h({cacheId:a.settings.NAME,filename:'service-worker.js',minify:!0,dontCacheBustUrlsMatching:/./,staticFileGlobsIgnorePatterns:[/\.map$/,/\.json$/],runtimeCaching:[{urlPattern:'/',handler:'networkFirst'}]})),process.env.npm_config_report){const a=require('webpack-bundle-analyzer');f.plugins.push(new a.BundleAnalyzerPlugin)}return f})}function GenerateStandaloneServerConfig(a){return __awaiter(this,void 0,void 0,function*(){const b=require('webpack'),c=require('webpack-node-externals'),d=[];'build'===a.settings.ENV&&d.push('babel-loader?presets[]=minify'),d.push('ts-loader?configFile='+resolveStandaloneServerConfigFile(a));const e=c();return{target:'node',entry:{standalone:resolveStandaloneServerEntryFile(a)},output:{path:join(a.settings.RELEASE_DIR,'bin'),filename:'[name]'},node:{__dirname:!1},externals:e,resolve:{extensions:['.ts']},module:{rules:[{test:/\.ts$/,loaders:d}]},plugins:[new b.BannerPlugin({banner:'#!/usr/bin/env node',raw:!0,entryOnly:!0})]}})}function union_arrays(a,b){let c={};for(let d=a.length-1;0<=d;--d)c[a[d]]=a[d];for(let d=b.length-1;0<=d;--d)c[b[d]]=b[d];let d=[];for(let e in c)c.hasOwnProperty(e)&&d.push(c[e]);return d}const NODE_EXTERNALS=['buffer','querystring','events','http','cluster','zlib','os','https','punycode','repl','readline','vm','child_process','url','dns','net','dgram','fs','path','string_decoder','tls','crypto','stream','util','assert','tty','domain','constants','module','process','v8','timers','console','async_hooks','http2','perf_hooks'];function GenerateExternalPackageNames(a){const b=parseJSON(a.root.file('package.json'));let c=NODE_EXTERNALS;if(b.dependencies){const a=Object.keys(b.dependencies);a.length&&(c=union_arrays(c,a))}if(b.devDependencies){const a=Object.keys(b.devDependencies);a.length&&(c=union_arrays(c,a))}return c}const fe$1=require('fs-extra');function GenerateServerlessConfig(a){return __awaiter(this,void 0,void 0,function*(){const b=a.file('handlers.ts'),c=require('rollup-plugin-typescript2'),d=require('rollup-plugin-babel-minify'),e=join(a.settings.HOME_DIR,'tsconfig.release.json'),f={cacheRoot:'/tmp/.rpt2_cache',tsconfig:'',tsconfigOverride:{compilerOptions:{target:'es6',module:'es2015'}}};f.tsconfig=fe$1.pathExistsSync(e)?e:a.file('tsconfig.json').path;const g={input:b.path,external:GenerateExternalPackageNames(a),plugins:[c(f),d({banner:'/* Enterprise Web Application Stack */',deadcode:{keepFnName:!0,keepFnArgs:!0,keepClassName:!0}})]},h={file:join(a.root.path,'release/handlers.js'),format:'cjs',sourcemap:!0};return{inputOptions:g,outputOptions:h}})}function GenerateServerlessTemplate(a){return __awaiter(this,void 0,void 0,function*(){let b={service:a.settings.NAME,package:{include:['conf/settings.yaml']},plugins:['serverless-apigw-binary'],custom:{apigwBinary:{types:['*/*']}},functions:{server:{handler:'handlers.server',timeout:a.settings.SERVERLESS_TIMEOUT_IN_SECONDS,access:'public',events:[{http:{path:'',method:'get'}},{http:{path:'',method:'head'}},{http:{path:'',method:'options'}},{http:{path:'{route+}',method:'get'}},{http:{path:'{route+}',method:'head'}},{http:{path:'{route+}',method:'options'}},{http:{path:'{route+}',method:'post'}},{http:{path:'{route+}',method:'put'}},{http:{path:'{route+}',method:'delete'}}]}}};return a.settings.SERVERLESS&&Object.keys(a.settings.SERVERLESS).length&&(b=Object.assign(b,a.settings.SERVERLESS)),b})}const fe$2=require('fs-extra');function copyIfExists(a,b,c){const d=join(a.settings.HOME_DIR,b),e=join(a.settings.RELEASE_DIR,c||b);return fe$2.pathExistsSync(d)?(fe$2.copySync(d,e),!0):!!(c&&fe$2.pathExistsSync(join(a.settings.RELEASE_DIR,c)))&&(fe$2.copySync(d,join(a.settings.RELEASE_DIR,c)),!0)}function removeIfExists(a,b){const c=join(a.settings.RELEASE_DIR,'public',b);if(fe$2.pathExistsSync(c))return fe$2.removeSync(c),!0}const fe$3=require('fs-extra'),fs=require('fs');function copyOrBuildPackageFile(a){const b=join(a.settings.HOME_DIR,'package.release.json'),c=join(a.settings.RELEASE_DIR,'package.json');if(fe$3.pathExistsSync(b))fe$3.copySync(b,c);else{const b=parseJSON(a.root.file('package.json'));Reflect.deleteProperty(b,'scripts'),Reflect.deleteProperty(b,'prettier'),Reflect.deleteProperty(b,'devDependencies'),fs.writeFileSync(c,JSON.stringify(b,null,2))}}const fe$4=require('fs-extra');class WebCompiler extends Application{generateWebpackBundles(){return __awaiter(this,void 0,void 0,function*(){const a=[];return this.settings.PUBLIC_DIR&&fe$4.pathExistsSync('src/webapp')&&a.push((yield GenerateWebappBrowserConfig(this))),a})}buildStandalone(){return __awaiter(this,void 0,void 0,function*(){const a=[yield GenerateStandaloneServerConfig(this)],b=require('webpack'),c=b(a);yield new Promise((a,b)=>{c.run((c,d)=>c?b(c):a(d))})})}standalone(){return __awaiter(this,void 0,void 0,function*(){return this.buildStandalone().catch((a)=>{this.log(`ignore standalone bundle because ${a.message}`)})})}buildWebpack(){return __awaiter(this,void 0,void 0,function*(){fe$4.pathExistsSync(this.settings.PUBLIC_DIR)&&(fe$4.ensureDirSync(join(this.settings.RELEASE_DIR,'public')),fe$4.copySync(this.settings.PUBLIC_DIR,join(this.settings.RELEASE_DIR,'public')));const a=yield this.generateWebpackBundles(),b=require('webpack'),c=b(a);yield new Promise((a,b)=>{c.run((c,d)=>c?b(c):a(d))})})}webpack(){return __awaiter(this,void 0,void 0,function*(){return this.buildWebpack().catch((a)=>{this.error(a,`ignore webpack bundle because ${a.message}`)})})}generateRollupBundles(){return __awaiter(this,void 0,void 0,function*(){return GenerateServerlessConfig(this)})}rollup(){return __awaiter(this,void 0,void 0,function*(){yield this.generateRollupBundles().then(({inputOptions:a,outputOptions:b})=>{const c=require('rollup');return c.rollup(a).then((a)=>a.generate(b).then(({code:c,map:d})=>a.write(b)))}).catch((a)=>{this.error(a,`ignore rollup bundle because ${a.message}`)})})}project(){return __awaiter(this,void 0,void 0,function*(){if(fe$4.pathExistsSync(join(this.settings.CONF_DIR,'production.yaml'))?(fe$4.ensureDirSync(join(this.settings.RELEASE_DIR,'conf')),fe$4.copySync(join(this.settings.CONF_DIR,'production.yaml'),join(this.settings.RELEASE_DIR,'conf/settings.yaml'))):fe$4.pathExistsSync(join(this.settings.CONF_DIR,'settings.yaml'))&&(fe$4.ensureDirSync(join(this.settings.RELEASE_DIR,'conf')),fe$4.copySync(join(this.settings.CONF_DIR,'settings.yaml'),join(this.settings.RELEASE_DIR,'conf/settings.yaml'))),copyIfExists(this,'Dockerfile'),copyIfExists(this,'COPYRIGHT'),copyIfExists(this,'LICENSE'),copyIfExists(this,'README.md'),copyIfExists(this,'yarn.lock'),copyOrBuildPackageFile(this),!copyIfExists(this,'serverless.yml')){const a=yield GenerateServerlessTemplate(this);dumpYAML(a,join(this.settings.RELEASE_DIR,'serverless.yml'))}removeIfExists(this,'index.template.html'),removeIfExists(this,'.gitignore')})}build(){return __awaiter(this,void 0,void 0,function*(){yield this.webpack(),yield this.standalone(),yield this.rollup()})}}class WebCompilerSettings extends ApplicationSettings{constructor(){super(...arguments),this.TITLE='',this.PUBLIC_DIR='',this.PUBLIC_URL='',this.USE_EXTERNAL_CDN=!0,this.RELEASE_DIR='release',this.SERVERLESS_TIMEOUT_IN_SECONDS=30}}__decorate([conf(),__metadata('design:type',String)],WebCompilerSettings.prototype,'TITLE',void 0),__decorate([conf(),__metadata('design:type',String)],WebCompilerSettings.prototype,'PUBLIC_DIR',void 0),__decorate([conf(),__metadata('design:type',String)],WebCompilerSettings.prototype,'PUBLIC_URL',void 0),__decorate([conf(),__metadata('design:type',Boolean)],WebCompilerSettings.prototype,'USE_EXTERNAL_CDN',void 0),__decorate([conf(),__metadata('design:type',String)],WebCompilerSettings.prototype,'RELEASE_DIR',void 0),__decorate([conf(),__metadata('design:type',Object)],WebCompilerSettings.prototype,'SERVERLESS',void 0),__decorate([conf(),__metadata('design:type',Number)],WebCompilerSettings.prototype,'SERVERLESS_TIMEOUT_IN_SECONDS',void 0);export{WebCompiler,WebCompilerSettings,GenerateStandaloneServerConfig,GenerateWebappBrowserConfig};