diff --git a/packages/webpack5/package.json b/packages/webpack5/package.json index b629dfbf1..8799f2e09 100644 --- a/packages/webpack5/package.json +++ b/packages/webpack5/package.json @@ -28,6 +28,7 @@ "ts-loader": "^8.0.11", "vue-loader": "^15.9.5", "webpack": "^5.6.0", + "webpack-bundle-analyzer": "^4.1.0", "webpack-chain": "^6.5.1", "webpack-cli": "^4.2.0", "webpack-merge": "^5.4.0", diff --git a/packages/webpack5/src/configuration/base.ts b/packages/webpack5/src/configuration/base.ts index c6798f003..b7188188f 100644 --- a/packages/webpack5/src/configuration/base.ts +++ b/packages/webpack5/src/configuration/base.ts @@ -8,12 +8,11 @@ import { getPlatform, } from '../helpers/project'; -import TransformNativeClass from '../transformers/NativeClass'; - import { CleanWebpackPlugin } from 'clean-webpack-plugin'; import { DefinePlugin } from 'webpack'; import { WatchStateLoggerPlugin } from '../plugins/WatchStateLoggerPlugin'; import TerserPlugin from 'terser-webpack-plugin'; +import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer'; export default function (config: Config, env: IWebpackEnv): Config { const entryPath = getEntryPath(); @@ -56,6 +55,22 @@ export default function (config: Config, env: IWebpackEnv): Config { }, ]); + config.optimization.splitChunks({ + cacheGroups: { + defaultVendor: { + test: /[\\/]node_modules[\\/]/, + priority: -10, + name: 'vendor', + chunks: 'all', + // test: (module) => { + // const moduleName = module.nameForCondition ? module.nameForCondition() : ''; + // return /[\\/]node_modules[\\/]/.test(moduleName); + // }, + // enforce: true + }, + }, + }); + // look for loaders in // - node_modules/@nativescript/webpack/dist/loaders // - node_modules @@ -107,7 +122,7 @@ export default function (config: Config, env: IWebpackEnv): Config { }, getCustomTransformers() { return { - before: [TransformNativeClass], + before: [require('../transformers/NativeClass')], }; }, }); @@ -127,8 +142,8 @@ export default function (config: Config, env: IWebpackEnv): Config { .use('apply-css-loader') .loader('apply-css-loader') .end() - .use('css-loader') - .loader('css-loader'); + .use('css2json-loader') + .loader('css2json-loader'); // set up scss config.module @@ -168,6 +183,8 @@ export default function (config: Config, env: IWebpackEnv): Config { // }, // ]); + config.plugin('BundleAnalyzerPlugin').use(BundleAnalyzerPlugin); + // add the WatchStateLogger plugin used to notify the CLI of build state config.plugin('WatchStateLoggerPlugin').use(WatchStateLoggerPlugin); diff --git a/packages/webpack5/src/loaders/apply-css-loader/index.ts b/packages/webpack5/src/loaders/apply-css-loader/index.ts index b41657bb0..17247d4ad 100644 --- a/packages/webpack5/src/loaders/apply-css-loader/index.ts +++ b/packages/webpack5/src/loaders/apply-css-loader/index.ts @@ -1,35 +1,34 @@ import { dedent } from 'ts-dedent'; const cssLoaderWarning = dedent` - The apply-css-loader requires the file to be pre-processed by css-loader. - Make sure css-loader is applied before apply-css-loader. + The apply-css-loader requires the file to be pre-processed by either css-loader or css2json-loader. + Make sure the appropriate loader is applied before apply-css-loader. `; -function hasCssLoader(loaders: any[], loaderIndex: number) { - return loaders - ?.slice(loaderIndex) - .some(({ path }) => path.includes('css-loader')); -} - export default function loader(content, map) { - // if (this.request.match(/\/app\.(css|scss|less|sass)$/)) { - // return content; - // } + const hasLoader = (loader: string) => { + return this.loaders + ?.slice(this.loaderIndex) + .some(({ path }) => path.includes(loader)); + }; - // Emit a warning if the file was not processed by the css-loader. - if (!hasCssLoader(this.loaders, this.loaderIndex)) { - this.emitWarning(new Error(cssLoaderWarning)); - } - - content = dedent` - /* CSS START */ + if (hasLoader('apply-css-loader')) { + // add a tag to the applied css + const tag = + this.mode === 'development' + ? `, ${JSON.stringify(this.resourcePath)}` + : ''; + content = dedent` ${content} - /* CSS END */ - - /* APPLY CSS */ + const { addTaggedAdditionalCSS } = require("@nativescript/core/ui/styling/style-scope"); + addTaggedAdditionalCSS(___CSS2JSON_LOADER_EXPORT___${tag}) + `; + } else if (hasLoader('css-loader')) { + content = dedent` + ${content} + // apply css const { Application } = require("@nativescript/core"); require("@nativescript/core/ui/styling/style-scope"); - if (___CSS_LOADER_EXPORT___ && typeof ___CSS_LOADER_EXPORT___.forEach === "function") { ___CSS_LOADER_EXPORT___.forEach(cssExport => { if (cssExport.length > 1 && cssExport[1]) { @@ -39,6 +38,9 @@ export default function loader(content, map) { }); } `; + } else { + this.emitWarning(new Error(cssLoaderWarning)); + } this.callback(null, content, map); } diff --git a/packages/webpack5/src/loaders/css2json-loader/index.ts b/packages/webpack5/src/loaders/css2json-loader/index.ts index 15052a361..e325b2be7 100644 --- a/packages/webpack5/src/loaders/css2json-loader/index.ts +++ b/packages/webpack5/src/loaders/css2json-loader/index.ts @@ -1,5 +1,6 @@ import { parse, Import, Stylesheet } from 'css'; import { urlToRequest } from 'loader-utils'; +import { dedent } from 'ts-dedent'; const betweenQuotesPattern = /('|")(.*?)\1/; const unpackUrlPattern = /url\(([^\)]+)\)/; @@ -33,9 +34,17 @@ export default function loader(content: string, map: any) { // map.mappings = map.mappings.replace(/;{2,}/, '') + const code = dedent` + /* CSS2JSON */ + ${dependencies.join('\n')} + + const ___CSS2JSON_LOADER_EXPORT___ = ${str} + + export default ___CSS2JSON_LOADER_EXPORT___ + `; this.callback( null, - `${dependencies.join('\n')}module.exports = ${str};`, + code, //`${dependencies.join('\n')}module.exports = ${str};`, null ); }