Facebook
From Federico Ricchiuto, 4 Years ago, written in JavaScript.
Embed
Download Paste or View Raw
Hits: 149
  1. const { join, relative, resolve, sep, dirname } = require("path");
  2.  
  3. const webpack = require("webpack");
  4. const nsWebpack = require("nativescript-dev-webpack");
  5. const nativescriptTarget = require("nativescript-dev-webpack/nativescript-target");
  6. const { nsReplaceBootstrap } = require("nativescript-dev-webpack/transformers/ns-replace-bootstrap");
  7. const { nsReplaceLazyLoader } = require("nativescript-dev-webpack/transformers/ns-replace-lazy-loader");
  8. const { nsSupportHmrNg } = require("nativescript-dev-webpack/transformers/ns-support-hmr-ng");
  9. const { getMainModulePath } = require("nativescript-dev-webpack/utils/ast-utils");
  10. const { getNoEmitOnErrorFromTSConfig } = require("nativescript-dev-webpack/utils/tsconfig-utils");
  11. const CleanWebpackPlugin = require("clean-webpack-plugin");
  12. const CopyWebpackPlugin = require("copy-webpack-plugin");
  13. const { BundleAnalyzerPlugin } = require("webpack-bundle-analyzer");
  14. const { NativeScriptWorkerPlugin } = require("nativescript-worker-loader/NativeScriptWorkerPlugin");
  15. const TerserPlugin = require("terser-webpack-plugin");
  16. const { getAngularCompilerPlugin } = require("nativescript-dev-webpack/plugins/NativeScriptAngularCompilerPlugin");
  17. const hashSalt = Date.now().toString();
  18.  
  19. module.exports = env => {
  20.     // Add your custom Activities, Services and other Android app components here.
  21.     const appComponents = [
  22.         "tns-core-modules/ui/frame",
  23.         "tns-core-modules/ui/frame/activity",
  24.     ];
  25.  
  26.     const platform = env && (env.android && "android" || env.ios && "ios");
  27.     if (!platform) {
  28.         throw new Error("You need to provide a target platform!");
  29.     }
  30.  
  31.     const AngularCompilerPlugin = getAngularCompilerPlugin(platform);
  32.     const projectRoot = __dirname;
  33.  
  34.     // Default destination inside platforms/<platform>/...
  35.     const dist = resolve(projectRoot, nsWebpack.getAppPath(platform, projectRoot));
  36.  
  37.     const {
  38.         // The 'appPath' and 'appResourcesPath' values are fetched from
  39.         // the nsconfig.json configuration file.
  40.         appPath = "src",
  41.         appResourcesPath = "App_Resources",
  42.  
  43.         // You can provide the following flags when running 'tns run android|ios'
  44.         aot, // --env.aot
  45.         snapshot, // --env.snapshot,
  46.         production, // --env.production
  47.         uglify, // --env.uglify
  48.         report, // --env.report
  49.         sourceMap, // --env.sourceMap
  50.         hiddenSourceMap, // --env.hiddenSourceMap
  51.         hmr, // --env.hmr,
  52.         unitTesting, // --env.unitTesting
  53.         verbose, // --env.verbose
  54.         snapshotInDocker, // --env.snapshotInDocker
  55.         skipSnapshotTools, // --env.skipSnapshotTools
  56.         compileSnapshot // --env.compileSnapshot
  57.     } = env;
  58.  
  59.     const useLibs = compileSnapshot;
  60.     const isAnySourceMapEnabled = !!sourceMap || !!hiddenSourceMap;
  61.     const externals = nsWebpack.getConvertedExternals(env.externals);
  62.     const appFullPath = resolve(projectRoot, appPath);
  63.     const appResourcesFullPath = resolve(projectRoot, appResourcesPath);
  64.     const tsConfigName = "tsconfig.tns.json";
  65.     const entryModule = `${nsWebpack.getEntryModule(appFullPath, platform)}.ts`;
  66.     const entryPath = `.${sep}${entryModule}`;
  67.     const entries = { bundle: entryPath };
  68.     const areCoreModulesExternal = Array.isArray(env.externals) && env.externals.some(e => e.indexOf("tns-core-modules") > -1);
  69.     if (platform === "ios" && !areCoreModulesExternal) {
  70.         entries["tns_modules/tns-core-modules/inspector_modules"] = "inspector_modules";
  71.     };
  72.  
  73.     const ngCompilerTransformers = [];
  74.     const additionalLazyModuleResources = [];
  75.     if (aot) {
  76.         ngCompilerTransformers.push(nsReplaceBootstrap);
  77.     }
  78.  
  79.     if (hmr) {
  80.         ngCompilerTransformers.push(nsSupportHmrNg);
  81.     }
  82.  
  83.     // when "@angular/core" is external, it's not included in the bundles. In this way, it will be used
  84.     // directly from node_modules and the Angular modules loader won't be able to resolve the lazy routes
  85.     // fixes https://github.com/NativeScript/nativescript-cli/issues/4024
  86.     if (env.externals && env.externals.indexOf("@angular/core") > -1) {
  87.         const appModuleRelativePath = getMainModulePath(resolve(appFullPath, entryModule), tsConfigName);
  88.         if (appModuleRelativePath) {
  89.             const appModuleFolderPath = dirname(resolve(appFullPath, appModuleRelativePath));
  90.             // include the lazy loader inside app module
  91.             ngCompilerTransformers.push(nsReplaceLazyLoader);
  92.             // include the new lazy loader path in the allowed ones
  93.             additionalLazyModuleResources.push(appModuleFolderPath);
  94.         }
  95.     }
  96.  
  97.     const ngCompilerPlugin = new AngularCompilerPlugin({
  98.         hostReplacementPaths: nsWebpack.getResolver([platform, "tns"]),
  99.         platformTransformers: ngCompilerTransformers.map(t => t(() => ngCompilerPlugin, resolve(appFullPath, entryModule), projectRoot)),
  100.         mainPath: join(appFullPath, entryModule),
  101.         tsConfigPath: join(__dirname, tsConfigName),
  102.         skipCodeGeneration: !aot,
  103.         sourceMap: !!isAnySourceMapEnabled,
  104.         additionalLazyModuleResources: additionalLazyModuleResources
  105.     });
  106.  
  107.     let sourceMapFilename = nsWebpack.getSourceMapFilename(hiddenSourceMap, __dirname, dist);
  108.  
  109.     const itemsToClean = [`${dist}/**/*`];
  110.     if (platform === "android") {
  111.         itemsToClean.push(`${join(projectRoot, "platforms", "android", "app", "src", "main", "assets", "snapshots")}`);
  112.         itemsToClean.push(`${join(projectRoot, "platforms", "android", "app", "build", "configurations", "nativescript-android-snapshot")}`);
  113.     }
  114.  
  115.     const noEmitOnErrorFromTSConfig = getNoEmitOnErrorFromTSConfig(join(projectRoot, tsConfigName));
  116.  
  117.     nsWebpack.processAppComponents(appComponents, platform);
  118.     const config = {
  119.         mode: production ? "production" : "development",
  120.         context: appFullPath,
  121.         externals,
  122.         watchOptions: {
  123.             ignored: [
  124.                 appResourcesFullPath,
  125.                 // Don't watch hidden files
  126.                 "**/.*",
  127.             ]
  128.         },
  129.         target: nativescriptTarget,
  130.         entry: entries,
  131.         output: {
  132.             pathinfo: false,
  133.             path: dist,
  134.             sourceMapFilename,
  135.             libraryTarget: "commonjs2",
  136.             filename: "[name].js",
  137.             globalObject: "global",
  138.             hashSalt
  139.         },
  140.         resolve: {
  141.             extensions: [".ts", ".js", ".scss", ".css"],
  142.             // Resolve {N} system modules from tns-core-modules
  143.             modules: [
  144.                 resolve(__dirname, "node_modules/tns-core-modules"),
  145.                 resolve(__dirname, "node_modules"),
  146.                 "node_modules/tns-core-modules",
  147.                 "node_modules",
  148.             ],
  149.             alias: {
  150.                 '~': appFullPath
  151.             },
  152.             symlinks: true
  153.         },
  154.         resolveLoader: {
  155.             symlinks: false
  156.         },
  157.         node: {
  158.             // Disable node shims that conflict with NativeScript
  159.             "http": false,
  160.             "timers": false,
  161.             "setImmediate": false,
  162.             "fs": "empty",
  163.             "__dirname": false,
  164.         },
  165.         devtool: hiddenSourceMap ? "hidden-source-map" : (sourceMap ? "inline-source-map" : "none"),
  166.         optimization: {
  167.             runtimeChunk: "single",
  168.             noEmitOnErrors: noEmitOnErrorFromTSConfig,
  169.             splitChunks: {
  170.                 cacheGroups: {
  171.                     vendor: {
  172.                         name: "vendor",
  173.                         chunks: "all",
  174.                         test: (module, chunks) => {
  175.                             const moduleName = module.nameForCondition ? module.nameForCondition() : '';
  176.                             return /[\\/]node_modules[\\/]/.test(moduleName) ||
  177.                                 appComponents.some(comp => comp === moduleName);
  178.                         },
  179.                         enforce: true,
  180.                     },
  181.                 }
  182.             },
  183.             minimize: !!uglify,
  184.             minimizer: [
  185.                 new TerserPlugin({
  186.                     parallel: true,
  187.                     cache: true,
  188.                     sourceMap: isAnySourceMapEnabled,
  189.                     terserOptions: {
  190.                         output: {
  191.                             comments: false,
  192.                             semicolons: !isAnySourceMapEnabled
  193.                         },
  194.                         compress: {
  195.                             // The Android SBG has problems parsing the output
  196.                             // when these options are enabled
  197.                             'collapse_vars': platform !== "android",
  198.                             sequences: platform !== "android",
  199.                         }
  200.                     }
  201.                 })
  202.             ],
  203.         },
  204.         module: {
  205.             rules: [
  206.                 {
  207.                     include: join(appFullPath, entryPath),
  208.                     use: [
  209.                         // Require all Android app components
  210.                         platform === "android" && {
  211.                             loader: "nativescript-dev-webpack/android-app-components-loader",
  212.                             options: { modules: appComponents }
  213.                         },
  214.  
  215.                         {
  216.                             loader: "nativescript-dev-webpack/bundle-config-loader",
  217.                             options: {
  218.                                 angular: true,
  219.                                 loadCss: !snapshot, // load the application css if in debug mode
  220.                                 unitTesting,
  221.                                 appFullPath,
  222.                                 projectRoot,
  223.                                 ignoredFiles: nsWebpack.getUserDefinedEntries(entries, platform)
  224.                             }
  225.                         },
  226.                     ].filter(loader => !!loader)
  227.                 },
  228.  
  229.                 { test: /\.html$|\.xml$/, use: "raw-loader" },
  230.  
  231.                 {
  232.                     test: /[\/|\\]app\.css$/,
  233.                     use: [
  234.                         "nativescript-dev-webpack/style-hot-loader",
  235.                         {
  236.                             loader: "nativescript-dev-webpack/css2json-loader",
  237.                             options: { useForImports: true }
  238.                         }
  239.                     ]
  240.                 },
  241.                 {
  242.                     test: /[\/|\\]app\.scss$/,
  243.                     use: [
  244.                         "nativescript-dev-webpack/style-hot-loader",
  245.                         {
  246.                             loader: "nativescript-dev-webpack/css2json-loader",
  247.                             options: { useForImports: true }
  248.                         },
  249.                         "sass-loader"
  250.                     ]
  251.                 },
  252.  
  253.                 // Angular components reference css files and their imports using raw-loader
  254.                 { test: /\.css$/, exclude: /[\/|\\]app\.css$/, use: "raw-loader" },
  255.                 { test: /\.scss$/, exclude: /[\/|\\]app\.scss$/, use: ["raw-loader", "resolve-url-loader", "sass-loader"] },
  256.  
  257.                 {
  258.                     test: /(?:\.ngfactory\.js|\.ngstyle\.js|\.ts)$/,
  259.                     use: [
  260.                         "nativescript-dev-webpack/moduleid-compat-loader",
  261.                         "nativescript-dev-webpack/lazy-ngmodule-hot-loader",
  262.                         "@ngtools/webpack",
  263.                     ]
  264.                 },
  265.  
  266.                 // Mark files inside `@angular/core` as using SystemJS style dynamic imports.
  267.                 // Removing this will cause deprecation warnings to appear.
  268.                 {
  269.                     test: /[\/\\]@angular[\/\\]core[\/\\].+\.js$/,
  270.                     parser: { system: true },
  271.                 },
  272.             ],
  273.         },
  274.         plugins: [
  275.             // Define useful constants like TNS_WEBPACK
  276.             new webpack.DefinePlugin({
  277.                 "global.TNS_WEBPACK": "true",
  278.                 "process": "global.process",
  279.             }),
  280.             // Remove all files from the out dir.
  281.             new CleanWebpackPlugin(itemsToClean, { verbose: !!verbose }),
  282.             // Copy assets to out dir. Add your own globs as needed.
  283.             new CopyWebpackPlugin([
  284.                 { from: { glob: "fonts/**" } },
  285.                 { from: { glob: "**/*.jpg" } },
  286.                 { from: { glob: "**/*.png" } },
  287.             ], { ignore: [`${relative(appPath, appResourcesFullPath)}/**`] }),
  288.             new nsWebpack.GenerateNativeScriptEntryPointsPlugin("bundle"),
  289.             // For instructions on how to set up workers with webpack
  290.             // check out https://github.com/nativescript/worker-loader
  291.             new NativeScriptWorkerPlugin(),
  292.             ngCompilerPlugin,
  293.             // Does IPC communication with the {N} CLI to notify events when running in watch mode.
  294.             new nsWebpack.WatchStateLoggerPlugin(),
  295.         ],
  296.     };
  297.  
  298.     if (report) {
  299.         // Generate report files for bundles content
  300.         config.plugins.push(new BundleAnalyzerPlugin({
  301.             analyzerMode: "static",
  302.             openAnalyzer: false,
  303.             generateStatsFile: true,
  304.             reportFilename: resolve(projectRoot, "report", `report.html`),
  305.             statsFilename: resolve(projectRoot, "report", `stats.json`),
  306.         }));
  307.     }
  308.  
  309.     if (snapshot) {
  310.         config.plugins.push(new nsWebpack.NativeScriptSnapshotPlugin({
  311.             chunk: "vendor",
  312.             angular: true,
  313.             requireModules: [
  314.                 "reflect-metadata",
  315.                 "@angular/platform-browser",
  316.                 "@angular/core",
  317.                 "@angular/common",
  318.                 "@angular/router",
  319.                 "nativescript-angular/platform-static",
  320.                 "nativescript-angular/router",
  321.             ],
  322.             projectRoot,
  323.             webpackConfig: config,
  324.             snapshotInDocker,
  325.             skipSnapshotTools,
  326.             useLibs
  327.         }));
  328.     }
  329.  
  330.     if (hmr) {
  331.         config.plugins.push(new webpack.HotModuleReplacementPlugin());
  332.     }
  333.  
  334.     return config;
  335. };
  336.