UNPKG

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