1- const { relative, resolve, join } = require ( "path" ) ;
1+ const { join , relative, resolve, sep } = require ( "path" ) ;
22
33const webpack = require ( "webpack" ) ;
44const nsWebpack = require ( "nativescript-dev-webpack" ) ;
55const nativescriptTarget = require ( "nativescript-dev-webpack/nativescript-target" ) ;
6+ const { nsReplaceBootstrap } = require ( "nativescript-dev-webpack/transformers/ns-replace-bootstrap" ) ;
67const CleanWebpackPlugin = require ( "clean-webpack-plugin" ) ;
78const CopyWebpackPlugin = require ( "copy-webpack-plugin" ) ;
89const { BundleAnalyzerPlugin } = require ( "webpack-bundle-analyzer" ) ;
910const { NativeScriptWorkerPlugin } = require ( "nativescript-worker-loader/NativeScriptWorkerPlugin" ) ;
1011const UglifyJsPlugin = require ( "uglifyjs-webpack-plugin" ) ;
12+ const { AngularCompilerPlugin } = require ( "@ngtools/webpack" ) ;
1113
1214module . exports = env => {
15+ // Add your custom Activities, Services and other Android app components here.
16+ const appComponents = [
17+ "tns-core-modules/ui/frame" ,
18+ "tns-core-modules/ui/frame/activity" ,
19+ ] ;
20+
1321 const platform = env && ( env . android && "android" || env . ios && "ios" ) ;
1422 if ( ! platform ) {
1523 throw new Error ( "You need to provide a target platform!" ) ;
1624 }
1725
18- const platforms = [ "ios" , "android" ] ;
1926 const projectRoot = __dirname ;
20- nsWebpack . loadAdditionalPlugins ( { projectDir : projectRoot } ) ;
2127
2228 // Default destination inside platforms/<platform>/...
2329 const dist = resolve ( projectRoot , nsWebpack . getAppPath ( platform , projectRoot ) ) ;
@@ -30,21 +36,37 @@ module.exports = env => {
3036 appPath = "app" ,
3137 appResourcesPath = "app/App_Resources" ,
3238
33- // Aot, snapshot, uglify and report can be enabled by providing
34- // the ` --env.snapshot`, `--env.uglify` or `--env.report` flags
35- // when running 'tns run android|ios'
36- aot ,
37- snapshot ,
38- uglify ,
39- report ,
39+ // You can provide the following flags when running 'tns run android|ios'
40+ aot , // --env.aot
41+ snapshot , // --env.snapshot
42+ uglify , // --env.uglify
43+ report , // --env.report
44+ sourceMap , // --env.sourceMap
45+ hmr , // --env.hmr ,
4046 } = env ;
41- const ngToolsWebpackOptions = { tsConfigPath : join ( __dirname , "tsconfig.json" ) } ;
47+ const externals = ( env . externals || [ ] ) . map ( ( e ) => { // --env.externals
48+ return new RegExp ( e + ".*" ) ;
49+ } ) ;
4250
4351 const appFullPath = resolve ( projectRoot , appPath ) ;
4452 const appResourcesFullPath = resolve ( projectRoot , appResourcesPath ) ;
4553
54+ const entryModule = `${ nsWebpack . getEntryModule ( appFullPath ) } .ts` ;
55+ const entryPath = `.${ sep } ${ entryModule } ` ;
56+
57+ const ngCompilerPlugin = new AngularCompilerPlugin ( {
58+ hostReplacementPaths : nsWebpack . getResolver ( [ platform , "tns" ] ) ,
59+ platformTransformers : aot ? [ nsReplaceBootstrap ( ( ) => ngCompilerPlugin ) ] : null ,
60+ mainPath : resolve ( appPath , entryModule ) ,
61+ tsConfigPath : join ( __dirname , "tsconfig.tns.json" ) ,
62+ skipCodeGeneration : ! aot ,
63+ sourceMap : ! ! sourceMap ,
64+ } ) ;
65+
4666 const config = {
67+ mode : uglify ? "production" : "development" ,
4768 context : appFullPath ,
69+ externals,
4870 watchOptions : {
4971 ignored : [
5072 appResourcesFullPath ,
@@ -54,16 +76,14 @@ module.exports = env => {
5476 } ,
5577 target : nativescriptTarget ,
5678 entry : {
57- bundle : aot ?
58- `./${ nsWebpack . getAotEntryModule ( appFullPath ) } ` :
59- `./${ nsWebpack . getEntryModule ( appFullPath ) } ` ,
60- vendor : "./vendor" ,
79+ bundle : entryPath ,
6180 } ,
6281 output : {
63- pathinfo : true ,
82+ pathinfo : false ,
6483 path : dist ,
6584 libraryTarget : "commonjs2" ,
6685 filename : "[name].js" ,
86+ globalObject : "global" ,
6787 } ,
6888 resolve : {
6989 extensions : [ ".ts" , ".js" , ".scss" , ".css" ] ,
@@ -88,9 +108,64 @@ module.exports = env => {
88108 "timers" : false ,
89109 "setImmediate" : false ,
90110 "fs" : "empty" ,
111+ "__dirname" : false ,
112+ } ,
113+ devtool : sourceMap ? "inline-source-map" : "none" ,
114+ optimization : {
115+ splitChunks : {
116+ cacheGroups : {
117+ vendor : {
118+ name : "vendor" ,
119+ chunks : "all" ,
120+ test : ( module , chunks ) => {
121+ const moduleName = module . nameForCondition ? module . nameForCondition ( ) : '' ;
122+ return / [ \\ / ] n o d e _ m o d u l e s [ \\ / ] / . test ( moduleName ) ||
123+ appComponents . some ( comp => comp === moduleName ) ;
124+ } ,
125+ enforce : true ,
126+ } ,
127+ }
128+ } ,
129+ minimize : ! ! uglify ,
130+ minimizer : [
131+ new UglifyJsPlugin ( {
132+ parallel : true ,
133+ cache : true ,
134+ uglifyOptions : {
135+ output : {
136+ comments : false ,
137+ } ,
138+ compress : {
139+ // The Android SBG has problems parsing the output
140+ // when these options are enabled
141+ 'collapse_vars' : platform !== "android" ,
142+ sequences : platform !== "android" ,
143+ }
144+ }
145+ } )
146+ ] ,
91147 } ,
92148 module : {
93149 rules : [
150+ {
151+ test : new RegExp ( entryPath ) ,
152+ use : [
153+ // Require all Android app components
154+ platform === "android" && {
155+ loader : "nativescript-dev-webpack/android-app-components-loader" ,
156+ options : { modules : appComponents }
157+ } ,
158+
159+ {
160+ loader : "nativescript-dev-webpack/bundle-config-loader" ,
161+ options : {
162+ angular : true ,
163+ loadCss : ! snapshot , // load the application css if in debug mode
164+ }
165+ } ,
166+ ] . filter ( loader => ! ! loader )
167+ } ,
168+
94169 { test : / \. h t m l $ | \. x m l $ / , use : "raw-loader" } ,
95170
96171 // tns-core-modules reads the app.css and its imports using css-loader
@@ -113,62 +188,59 @@ module.exports = env => {
113188 { test : / \. c s s $ / , exclude : / [ \/ | \\ ] a p p \. c s s $ / , use : "raw-loader" } ,
114189 { test : / \. s c s s $ / , exclude : / [ \/ | \\ ] a p p \. s c s s $ / , use : [ "raw-loader" , "resolve-url-loader" , "sass-loader" ] } ,
115190
116- // Compile TypeScript files with ahead-of-time compiler.
117- { test : / .t s $ / , use : [
118- "nativescript-dev-webpack/moduleid-compat-loader" ,
119- { loader : "@ngtools/webpack" , options : ngToolsWebpackOptions } ,
120- ] } ,
191+ {
192+ test : / (?: \. n g f a c t o r y \. j s | \. n g s t y l e \. j s | \. t s ) $ / ,
193+ use : [
194+ "nativescript-dev-webpack/moduleid-compat-loader" ,
195+ "@ngtools/webpack" ,
196+ ]
197+ } ,
198+
199+ // Mark files inside `@angular/core` as using SystemJS style dynamic imports.
200+ // Removing this will cause deprecation warnings to appear.
201+ {
202+ test : / [ \/ \\ ] @ a n g u l a r [ \/ \\ ] c o r e [ \/ \\ ] .+ \. j s $ / ,
203+ parser : { system : true } ,
204+ } ,
121205 ] ,
122206 } ,
123207 plugins : [
124- // Vendor libs go to the vendor.js chunk
125- new webpack . optimize . CommonsChunkPlugin ( {
126- name : [ "vendor" ] ,
127- } ) ,
128208 // Define useful constants like TNS_WEBPACK
129209 new webpack . DefinePlugin ( {
130210 "global.TNS_WEBPACK" : "true" ,
211+ "process" : undefined ,
131212 } ) ,
132213 // Remove all files from the out dir.
133- new CleanWebpackPlugin ( [ `${ dist } /**/*` ] ) ,
214+ new CleanWebpackPlugin ( [ `${ dist } /**/*` ] ) ,
134215 // Copy native app resources to out dir.
135216 new CopyWebpackPlugin ( [
136- {
137- from : `${ appResourcesFullPath } /${ appResourcesPlatformDir } ` ,
138- to : `${ dist } /App_Resources/${ appResourcesPlatformDir } ` ,
139- context : projectRoot
140- } ,
217+ {
218+ from : `${ appResourcesFullPath } /${ appResourcesPlatformDir } ` ,
219+ to : `${ dist } /App_Resources/${ appResourcesPlatformDir } ` ,
220+ context : projectRoot
221+ } ,
141222 ] ) ,
142223 // Copy assets to out dir. Add your own globs as needed.
143224 new CopyWebpackPlugin ( [
144- { from : "fonts/**" } ,
145- { from : "**/*.jpg" } ,
146- { from : "**/*.png" } ,
147- { from : "**/*.xml" } ,
225+ { from : { glob : "fonts/**" } } ,
226+ { from : { glob : "**/*.jpg" } } ,
227+ { from : { glob : "**/*.png" } } ,
148228 ] , { ignore : [ `${ relative ( appPath , appResourcesFullPath ) } /**` ] } ) ,
149229 // Generate a bundle starter script and activate it in package.json
150230 new nsWebpack . GenerateBundleStarterPlugin ( [
151231 "./vendor" ,
152232 "./bundle" ,
153233 ] ) ,
154- // Support for web workers since v3.2
234+ // For instructions on how to set up workers with webpack
235+ // check out https://github.com/nativescript/worker-loader
155236 new NativeScriptWorkerPlugin ( ) ,
156- // AngularCompilerPlugin with augmented NativeScript filesystem to handle platform specific resource resolution.
157- new nsWebpack . NativeScriptAngularCompilerPlugin (
158- Object . assign ( {
159- entryModule : resolve ( appPath , "app.module#AppModule" ) ,
160- skipCodeGeneration : ! aot ,
161- platformOptions : {
162- platform,
163- platforms,
164- // ignore: ["App_Resources"]
165- } ,
166- } , ngToolsWebpackOptions )
167- ) ,
237+ ngCompilerPlugin ,
168238 // Does IPC communication with the {N} CLI to notify events when running in watch mode.
169239 new nsWebpack . WatchStateLoggerPlugin ( ) ,
170240 ] ,
171241 } ;
242+
243+
172244 if ( report ) {
173245 // Generate report files for bundles content
174246 config . plugins . push ( new BundleAnalyzerPlugin ( {
@@ -179,26 +251,28 @@ module.exports = env => {
179251 statsFilename : resolve ( projectRoot , "report" , `stats.json` ) ,
180252 } ) ) ;
181253 }
254+
182255 if ( snapshot ) {
183256 config . plugins . push ( new nsWebpack . NativeScriptSnapshotPlugin ( {
184257 chunk : "vendor" ,
258+ angular : true ,
259+ requireModules : [
260+ "reflect-metadata" ,
261+ "@angular/platform-browser" ,
262+ "@angular/core" ,
263+ "@angular/common" ,
264+ "@angular/router" ,
265+ "nativescript-angular/platform-static" ,
266+ "nativescript-angular/router" ,
267+ ] ,
185268 projectRoot,
186269 webpackConfig : config ,
187- targetArchs : [ "arm" , "arm64" , "ia32" ] ,
188- tnsJavaClassesOptions : { packages : [ "tns-core-modules" ] } ,
189- useLibs : false
190270 } ) ) ;
191271 }
192- if ( uglify ) {
193- config . plugins . push ( new webpack . LoaderOptionsPlugin ( { minimize : true } ) ) ;
194-
195- // Work around an Android issue by setting compress = false
196- const compress = platform !== "android" ;
197- config . plugins . push ( new UglifyJsPlugin ( {
198- uglifyOptions : {
199- compress,
200- }
201- } ) ) ;
272+
273+ if ( hmr ) {
274+ config . plugins . push ( new webpack . HotModuleReplacementPlugin ( ) ) ;
202275 }
276+
203277 return config ;
204278} ;
0 commit comments