webpack.config.js 10 KB

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