webpack.config.js 9.6 KB

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