UNPKG

9.16 kBJavaScriptView Raw
1const { join, relative, resolve, sep } = require("path");
2
3const webpack = require("webpack");
4const nsWebpack = require("nativescript-dev-webpack");
5const nativescriptTarget = require("nativescript-dev-webpack/nativescript-target");
6const CleanWebpackPlugin = require("clean-webpack-plugin");
7const CopyWebpackPlugin = require("copy-webpack-plugin");
8const { BundleAnalyzerPlugin } = require("webpack-bundle-analyzer");
9const { NativeScriptWorkerPlugin } = require("nativescript-worker-loader/NativeScriptWorkerPlugin");
10const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
11
12module.exports = env => {
13 // Add your custom Activities, Services and other android app components here.
14 const appComponents = [
15 "tns-core-modules/ui/frame",
16 "tns-core-modules/ui/frame/activity",
17 ];
18
19 const platform = env && (env.android && "android" || env.ios && "ios");
20 if (!platform) {
21 throw new Error("You need to provide a target platform!");
22 }
23
24 const platforms = ["ios", "android"];
25 const projectRoot = __dirname;
26
27 // Default destination inside platforms/<platform>/...
28 const dist = resolve(projectRoot, nsWebpack.getAppPath(platform, projectRoot));
29 const appResourcesPlatformDir = platform === "android" ? "Android" : "iOS";
30
31 const {
32 // The 'appPath' and 'appResourcesPath' values are fetched from
33 // the nsconfig.json configuration file
34 // when bundling with `tns run android|ios --bundle`.
35 appPath = "app",
36 appResourcesPath = "app/App_Resources",
37
38 // You can provide the following flags when running 'tns run android|ios'
39 snapshot, // --env.snapshot
40 uglify, // --env.uglify
41 report, // --env.report
42 sourceMap, // --env.sourceMap
43 hmr, // --env.hmr,
44 } = env;
45 const externals = nsWebpack.getConvertedExternals(env.externals);
46
47 const appFullPath = resolve(projectRoot, appPath);
48 const appResourcesFullPath = resolve(projectRoot, appResourcesPath);
49
50 const entryModule = nsWebpack.getEntryModule(appFullPath);
51 const entryPath = `.${sep}${entryModule}.js`;
52
53 const config = {
54 mode: uglify ? "production" : "development",
55 context: appFullPath,
56 externals,
57 watchOptions: {
58 ignored: [
59 appResourcesFullPath,
60 // Don't watch hidden files
61 "**/.*",
62 ]
63 },
64 target: nativescriptTarget,
65 entry: {
66 bundle: entryPath,
67 },
68 output: {
69 pathinfo: false,
70 path: dist,
71 libraryTarget: "commonjs2",
72 filename: "[name].js",
73 globalObject: "global",
74 },
75 resolve: {
76 extensions: [".js", ".scss", ".css"],
77 // Resolve {N} system modules from tns-core-modules
78 modules: [
79 "node_modules/tns-core-modules",
80 "node_modules",
81 ],
82 alias: {
83 '~': appFullPath
84 },
85 // don't resolve symlinks to symlinked modules
86 symlinks: false
87 },
88 resolveLoader: {
89 // don't resolve symlinks to symlinked loaders
90 symlinks: false
91 },
92 node: {
93 // Disable node shims that conflict with NativeScript
94 "http": false,
95 "timers": false,
96 "setImmediate": false,
97 "fs": "empty",
98 "__dirname": false,
99 },
100 devtool: sourceMap ? "inline-source-map" : "none",
101 optimization: {
102 splitChunks: {
103 cacheGroups: {
104 vendor: {
105 name: "vendor",
106 chunks: "all",
107 test: (module, chunks) => {
108 const moduleName = module.nameForCondition ? module.nameForCondition() : '';
109 return /[\\/]node_modules[\\/]/.test(moduleName) ||
110 appComponents.some(comp => comp === moduleName);
111
112 },
113 enforce: true,
114 },
115 }
116 },
117 minimize: !!uglify,
118 minimizer: [
119 new UglifyJsPlugin({
120 parallel: true,
121 cache: true,
122 uglifyOptions: {
123 output: {
124 comments: false,
125 },
126 compress: {
127 // The Android SBG has problems parsing the output
128 // when these options are enabled
129 'collapse_vars': platform !== "android",
130 sequences: platform !== "android",
131 }
132 }
133 })
134 ],
135 },
136 module: {
137 rules: [
138 {
139 test: new RegExp(entryPath),
140 use: [
141 // Require all Android app components
142 platform === "android" && {
143 loader: "nativescript-dev-webpack/android-app-components-loader",
144 options: { modules: appComponents }
145 },
146
147 {
148 loader: "nativescript-dev-webpack/bundle-config-loader",
149 options: {
150 loadCss: !snapshot, // load the application css if in debug mode
151 }
152 },
153 ].filter(loader => !!loader)
154 },
155
156 {
157 test: /-page\.js$/,
158 use: "nativescript-dev-webpack/script-hot-loader"
159 },
160
161 {
162 test: /\.(css|scss)$/,
163 use: "nativescript-dev-webpack/style-hot-loader"
164 },
165
166 {
167 test: /\.(html|xml)$/,
168 use: "nativescript-dev-webpack/markup-hot-loader"
169 },
170
171 { test: /\.(html|xml)$/, use: "nativescript-dev-webpack/xml-namespace-loader"},
172
173 {
174 test: /\.css$/,
175 use: { loader: "css-loader", options: { minimize: false, url: false } }
176 },
177
178 {
179 test: /\.scss$/,
180 use: [
181 { loader: "css-loader", options: { minimize: false, url: false } },
182 "sass-loader"
183 ]
184 },
185 ]
186 },
187 plugins: [
188 // Define useful constants like TNS_WEBPACK
189 new webpack.DefinePlugin({
190 "global.TNS_WEBPACK": "true",
191 "process": undefined,
192 }),
193 // Remove all files from the out dir.
194 new CleanWebpackPlugin([ `${dist}/**/*` ]),
195 // Copy native app resources to out dir.
196 new CopyWebpackPlugin([
197 {
198 from: `${appResourcesFullPath}/${appResourcesPlatformDir}`,
199 to: `${dist}/App_Resources/${appResourcesPlatformDir}`,
200 context: projectRoot
201 },
202 ]),
203 // Copy assets to out dir. Add your own globs as needed.
204 new CopyWebpackPlugin([
205 { from: { glob: "fonts/**" } },
206 { from: { glob: "**/*.jpg" } },
207 { from: { glob: "**/*.png" } },
208 ], { ignore: [`${relative(appPath, appResourcesFullPath)}/**`] }),
209 // Generate a bundle starter script and activate it in package.json
210 new nsWebpack.GenerateBundleStarterPlugin([
211 "./vendor",
212 "./bundle",
213 ]),
214 // For instructions on how to set up workers with webpack
215 // check out https://github.com/nativescript/worker-loader
216 new NativeScriptWorkerPlugin(),
217 new nsWebpack.PlatformFSPlugin({
218 platform,
219 platforms,
220 }),
221 // Does IPC communication with the {N} CLI to notify events when running in watch mode.
222 new nsWebpack.WatchStateLoggerPlugin(),
223 ],
224 };
225
226 if (report) {
227 // Generate report files for bundles content
228 config.plugins.push(new BundleAnalyzerPlugin({
229 analyzerMode: "static",
230 openAnalyzer: false,
231 generateStatsFile: true,
232 reportFilename: resolve(projectRoot, "report", `report.html`),
233 statsFilename: resolve(projectRoot, "report", `stats.json`),
234 }));
235 }
236
237 if (snapshot) {
238 config.plugins.push(new nsWebpack.NativeScriptSnapshotPlugin({
239 chunk: "vendor",
240 requireModules: [
241 "tns-core-modules/bundle-entry-points",
242 ],
243 projectRoot,
244 webpackConfig: config,
245 }));
246 }
247
248 if (hmr) {
249 config.plugins.push(new webpack.HotModuleReplacementPlugin());
250 }
251
252
253 return config;
254};