@flatjs/evolve 2.1.0-next.10 → 2.1.0-next.12

Sign up to get free protection for your applications and to get access to all the features.
Files changed (126) hide show
  1. package/dist/constants.js +36 -1
  2. package/dist/create-webpack/create-externals.js +6 -1
  3. package/dist/create-webpack/create-optimization.js +43 -1
  4. package/dist/create-webpack/create-output.js +35 -1
  5. package/dist/create-webpack/create-performance.js +7 -1
  6. package/dist/create-webpack/create-plugins.js +78 -1
  7. package/dist/create-webpack/create-resolve.js +37 -1
  8. package/dist/create-webpack/create-rule-sets.js +20 -1
  9. package/dist/create-webpack/load-webpack-config.js +57 -1
  10. package/dist/create-webpack/resolve-public-path.js +15 -1
  11. package/dist/create-webpack/rule-sets/constants.js +3 -1
  12. package/dist/create-webpack/rule-sets/rule-assets.js +52 -1
  13. package/dist/create-webpack/rule-sets/rule-css.js +111 -1
  14. package/dist/create-webpack/rule-sets/rule-less.js +44 -1
  15. package/dist/create-webpack/rule-sets/rule-scripts.js +34 -1
  16. package/dist/create-webpack/rule-sets/rule-svg-icon.js +25 -1
  17. package/dist/create-webpack/rule-sets/rule-utils.js +10 -1
  18. package/dist/create-webpack/types.js +1 -1
  19. package/dist/default-options.js +83 -1
  20. package/dist/define-config/define-config.js +4 -1
  21. package/dist/define-config/index.js +1 -1
  22. package/dist/dev-server/add-compiler-to-dev-server.js +58 -1
  23. package/dist/dev-server/create-app-page-route.js +13 -1
  24. package/dist/dev-server/create-dev-server-compiler-task.js +55 -1
  25. package/dist/dev-server/create-dev-server-entries.js +25 -1
  26. package/dist/dev-server/create-dev-server.js +24 -1
  27. package/dist/dev-server/index.js +6 -1
  28. package/dist/dev-server/middlewares/create-page-middleware.js +33 -1
  29. package/dist/dev-server/middlewares/create-public-assets-middleware.js +25 -1
  30. package/dist/dev-server/middlewares/get-all-sorted-modules.js +24 -1
  31. package/dist/dev-server/middlewares/get-bundle-asset.js +7 -1
  32. package/dist/dev-server/middlewares/get-dev-server-host-uri.js +5 -1
  33. package/dist/dev-server/middlewares/get-hmr-runtime-chunks.js +14 -1
  34. package/dist/dev-server/middlewares/get-normalized-entry-name.js +14 -1
  35. package/dist/dev-server/middlewares/get-page-main-html.js +49 -1
  36. package/dist/dev-server/middlewares/get-page-module-html.js +123 -1
  37. package/dist/dev-server/middlewares/get-project-virtual-path.js +3 -1
  38. package/dist/dev-server/middlewares/get-runtime-manifest.js +25 -1
  39. package/dist/dev-server/middlewares/index.js +2 -1
  40. package/dist/dev-server/middlewares/types.js +1 -1
  41. package/dist/errors/evolve-build-error.js +10 -1
  42. package/dist/helpers/allow-px2rem-for-module.js +6 -1
  43. package/dist/helpers/assert-group-entry-item.js +19 -1
  44. package/dist/helpers/assert-single-compiler.js +45 -1
  45. package/dist/helpers/chunk-entry-map.js +21 -1
  46. package/dist/helpers/delete-object-keys.js +20 -1
  47. package/dist/helpers/enable-bundle-hashname-for-module.js +6 -1
  48. package/dist/helpers/filter-actived-entries.js +42 -1
  49. package/dist/helpers/flat-entry-map.js +11 -1
  50. package/dist/helpers/get-bundle-file-name.js +23 -1
  51. package/dist/helpers/get-git-root.js +4 -1
  52. package/dist/helpers/get-html-plugin-config.js +47 -1
  53. package/dist/helpers/get-max-process-tasks.js +7 -1
  54. package/dist/helpers/get-pacakge-dir.js +13 -1
  55. package/dist/helpers/get-runtime-cdn-base.js +21 -1
  56. package/dist/helpers/index.js +27 -1
  57. package/dist/helpers/is-deep-equal.js +67 -1
  58. package/dist/helpers/json-serializer.js +52 -1
  59. package/dist/helpers/merge-babel-options.js +45 -1
  60. package/dist/helpers/normalize-check-entry-options.js +28 -1
  61. package/dist/helpers/normalize-entry-map.js +59 -1
  62. package/dist/helpers/normalize-group-name.js +16 -1
  63. package/dist/helpers/normalize-page-proxy.js +9 -1
  64. package/dist/helpers/normalize-resolve-alias.js +7 -1
  65. package/dist/helpers/normalize-template-inject-tokens.js +22 -1
  66. package/dist/helpers/open-page.js +15 -1
  67. package/dist/helpers/print-log.js +49 -1
  68. package/dist/helpers/refresh-evolve-mock-options.js +34 -1
  69. package/dist/helpers/resolve-entry-map-input-files.js +20 -1
  70. package/dist/helpers/script-injects.js +39 -1
  71. package/dist/helpers/should-enable-react-fast-refresh.js +14 -1
  72. package/dist/helpers/split-to-entry-group.d.ts +5 -5
  73. package/dist/helpers/split-to-entry-group.js +139 -1
  74. package/dist/helpers/verify-group-entry-options.js +21 -1
  75. package/dist/index.js +5 -1
  76. package/dist/load-config/index.js +1 -1
  77. package/dist/load-config/load-evolve-config.js +41 -1
  78. package/dist/load-config/types.js +1 -1
  79. package/dist/main/create-thread-worker.js +51 -1
  80. package/dist/main/env-verify.js +21 -1
  81. package/dist/main/get-worker-path.js +5 -1
  82. package/dist/main/index.js +4 -1
  83. package/dist/main/prepare-build.js +39 -1
  84. package/dist/main/prepare-serve.js +69 -1
  85. package/dist/main/prepare-static.js +30 -1
  86. package/dist/main/start-build-dynamic.js +171 -1
  87. package/dist/main/start-build-worker.js +44 -1
  88. package/dist/main/start-build.js +69 -1
  89. package/dist/main/start-group-entry-build.js +32 -1
  90. package/dist/main/start-serve.js +34 -1
  91. package/dist/main/start-static.js +19 -1
  92. package/dist/minimizer/create-minimizers.js +25 -1
  93. package/dist/minimizer/default-options.js +14 -1
  94. package/dist/minimizer/image-minimizer.js +65 -1
  95. package/dist/minimizer/index.js +1 -1
  96. package/dist/minimizer/terser-minimizer.js +15 -3
  97. package/dist/minimizer/types.js +1 -1
  98. package/dist/plugins/circular-dependency/circular-dependency-plugin.js +119 -1
  99. package/dist/plugins/circular-dependency/index.js +15 -1
  100. package/dist/plugins/clean-webpack/clean-webpack-plugin.js +173 -1
  101. package/dist/plugins/clean-webpack/index.js +22 -1
  102. package/dist/plugins/define-variable/define-variable-plugin.js +28 -1
  103. package/dist/plugins/define-variable/index.js +1 -1
  104. package/dist/plugins/html-inject-scripts/plugin-html-inject-script.js +27 -1
  105. package/dist/plugins/module-federation/external-template-remotes.js +92 -1
  106. package/dist/plugins/module-federation/index.js +1 -1
  107. package/dist/plugins/module-federation/module-federation.js +100 -1
  108. package/dist/plugins/multi-html/index.js +16 -1
  109. package/dist/plugins/multi-html/multi-html-cdn-plugin.js +83 -1
  110. package/dist/plugins/multi-html/multi-html-plugin.js +65 -1
  111. package/dist/plugins/ts-checker/index.js +1 -1
  112. package/dist/plugins/ts-checker/ts-checker-plugin.js +24 -1
  113. package/dist/types/index.js +8 -1
  114. package/dist/types/types-ci.js +1 -1
  115. package/dist/types/types-dev-server.js +1 -1
  116. package/dist/types/types-entry-map.js +1 -1
  117. package/dist/types/types-federation.js +1 -1
  118. package/dist/types/types-loader-options.d.ts +30 -3
  119. package/dist/types/types-loader-options.js +1 -1
  120. package/dist/types/types-modular-import.js +1 -1
  121. package/dist/types/types-multi-html.js +1 -1
  122. package/dist/types/types-options.js +1 -1
  123. package/dist/types/types-plugin-options.js +1 -1
  124. package/dist/types/types-threads-options.js +1 -1
  125. package/dist/types/types-webpack.js +1 -1
  126. package/package.json +2 -2
package/dist/constants.js CHANGED
@@ -1 +1,36 @@
1
- export const moduleName="@flatjs/evolve";export const configFileName="flatjs-evolve";export const viewportScripts='(function(d){var j;var b=1;var i=1;var h=750;var c=100;function e(s,o){var q=d.document;var l=q.documentElement;var k=navigator.userAgent;var m=k.toLowerCase().indexOf("android")>-1;i=d.devicePixelRatio||1;if(i>3){i=3}if(m){i=1}console.log("current devicePixelRatio:",i);l.setAttribute("data-dpr",i.toString());var p=q.querySelector(\'meta[name="viewport"]\');if(!p){b=1/i;p=q.createElement("meta");p.setAttribute("name","viewport");q.head.appendChild(p);p.setAttribute(["content","width=device-width,user-scalable=no,initial-scale=",b,",maximum-scale=",b,",minimum-scale=",b].join(""))}function n(){var t=document.documentElement.clientWidth;j=t/o*(s/i)*i;q.documentElement.style.fontSize=String(j)+"px"}var r;d.addEventListener("resize",function(){clearTimeout(r);r=setTimeout(n,300)},false);d.addEventListener("onload",n,false);n()}e(c,h);window.fabricViewport={currRem:j,currDpr:i,currScale:b,dpiPX2px:function f(k){return parseFloat(k.toString())/j*100+"px"},px2DPIpx:function a(k){return parseFloat(k.toString())/100*j+"px"},px2rem:function g(k){return parseFloat(k.toString())/100+"rem"}}})(window);';export const polyfill=["https://polyfill.io/v3/polyfill.min.js?features=Array.from%2CArray.isArray%2CArray.of%2CArray.prototype.entries%2CArray.prototype.every%2CArray.prototype.fill%2CArray.prototype.filter%2CArray.prototype.find%2CArray.prototype.findIndex%2CArray.prototype.flat%2CArray.prototype.forEach%2CArray.prototype.flatMap%2CArray.prototype.keys%2CArray.prototype.indexOf%2CArray.prototype.includes%2CArray.prototype.lastIndexOf%2CArray.prototype.map%2CArray.prototype.reduce%2CArray.prototype.reduceRight%2CArray.prototype.some%2CArray.prototype.sort%2CArray.prototype.values%2CArrayBuffer%2CBlob%2CDataView%2CDate.now%2CObject.assign%2CObject.create%2CObject.defineProperties%2CObject.defineProperty%2CObject.entries%2CObject.freeze%2CObject.fromEntries%2CObject.getOwnPropertySymbols%2CObject.getOwnPropertyNames%2CObject.getOwnPropertyDescriptors%2CObject.getOwnPropertyDescriptor%2CObject.getPrototypeOf%2CObject.is%2CObject.isExtensible%2CObject.isFrozen%2CObject.isSealed%2CObject.keys%2CObject.values%2CObject.setPrototypeOf%2CPromise%2CPromise.prototype.finally%2CReflect%2CReflect.apply%2CReflect.construct%2CReflect.defineProperty%2CReflect.deleteProperty%2CReflect.getPrototypeOf%2CReflect.getOwnPropertyDescriptor%2CReflect.get%2CReflect.ownKeys%2CReflect.isExtensible%2CReflect.has%2CReflect.preventExtensions%2CReflect.set%2CReflect.setPrototypeOf%2CSet%2CString.prototype.trimStart%2CString.prototype.trimEnd%2CString.prototype.trim%2CString.prototype.startsWith%2CString.prototype.repeat%2CString.prototype.replaceAll%2CString.prototype.padStart%2CString.prototype.padEnd%2CMap%2CObject.seal%2Cconsole.groupEnd%2Cconsole.group"];export const devReactFastRefresh={runtime:"reactRefreshRuntime",reactRefreshSetup:"reactRefreshSetup"};export const ignoreEntryOptionKeys=["title"];export const maxEntryGroupSize=10;
1
+ export const moduleName = `@flatjs/evolve`;
2
+ /**
3
+ * the configuration file of `flat-evolve`
4
+ * flatjs-evolve.config.ts,.mjs,.mts
5
+ */
6
+ export const configFileName = `flatjs-evolve`;
7
+ /**
8
+ * `viewport.js`, Used to support the mobile `rem` adaptive solution.
9
+ * The viewport code is dynamically inserted to `html` file via `html-plugin`
10
+ */
11
+ export const viewportScripts = `(function(d){var j;var b=1;var i=1;var h=750;var c=100;function e(s,o){var q=d.document;var l=q.documentElement;var k=navigator.userAgent;var m=k.toLowerCase().indexOf("android")>-1;i=d.devicePixelRatio||1;if(i>3){i=3}if(m){i=1}console.log("current devicePixelRatio:",i);l.setAttribute("data-dpr",i.toString());var p=q.querySelector('meta[name="viewport"]');if(!p){b=1/i;p=q.createElement("meta");p.setAttribute("name","viewport");q.head.appendChild(p);p.setAttribute(["content","width=device-width,user-scalable=no,initial-scale=",b,",maximum-scale=",b,",minimum-scale=",b].join(""))}function n(){var t=document.documentElement.clientWidth;j=t/o*(s/i)*i;q.documentElement.style.fontSize=String(j)+"px"}var r;d.addEventListener("resize",function(){clearTimeout(r);r=setTimeout(n,300)},false);d.addEventListener("onload",n,false);n()}e(c,h);window.fabricViewport={currRem:j,currDpr:i,currScale:b,dpiPX2px:function f(k){return parseFloat(k.toString())/j*100+"px"},px2DPIpx:function a(k){return parseFloat(k.toString())/100*j+"px"},px2rem:function g(k){return parseFloat(k.toString())/100+"rem"}}})(window);`;
12
+ /**
13
+ * https://polyfill.io
14
+ */
15
+ export const polyfill = [
16
+ `https://polyfill.io/v3/polyfill.min.js?features=Array.from%2CArray.isArray%2CArray.of%2CArray.prototype.entries%2CArray.prototype.every%2CArray.prototype.fill%2CArray.prototype.filter%2CArray.prototype.find%2CArray.prototype.findIndex%2CArray.prototype.flat%2CArray.prototype.forEach%2CArray.prototype.flatMap%2CArray.prototype.keys%2CArray.prototype.indexOf%2CArray.prototype.includes%2CArray.prototype.lastIndexOf%2CArray.prototype.map%2CArray.prototype.reduce%2CArray.prototype.reduceRight%2CArray.prototype.some%2CArray.prototype.sort%2CArray.prototype.values%2CArrayBuffer%2CBlob%2CDataView%2CDate.now%2CObject.assign%2CObject.create%2CObject.defineProperties%2CObject.defineProperty%2CObject.entries%2CObject.freeze%2CObject.fromEntries%2CObject.getOwnPropertySymbols%2CObject.getOwnPropertyNames%2CObject.getOwnPropertyDescriptors%2CObject.getOwnPropertyDescriptor%2CObject.getPrototypeOf%2CObject.is%2CObject.isExtensible%2CObject.isFrozen%2CObject.isSealed%2CObject.keys%2CObject.values%2CObject.setPrototypeOf%2CPromise%2CPromise.prototype.finally%2CReflect%2CReflect.apply%2CReflect.construct%2CReflect.defineProperty%2CReflect.deleteProperty%2CReflect.getPrototypeOf%2CReflect.getOwnPropertyDescriptor%2CReflect.get%2CReflect.ownKeys%2CReflect.isExtensible%2CReflect.has%2CReflect.preventExtensions%2CReflect.set%2CReflect.setPrototypeOf%2CSet%2CString.prototype.trimStart%2CString.prototype.trimEnd%2CString.prototype.trim%2CString.prototype.startsWith%2CString.prototype.repeat%2CString.prototype.replaceAll%2CString.prototype.padStart%2CString.prototype.padEnd%2CMap%2CObject.seal%2Cconsole.groupEnd%2Cconsole.group`,
17
+ ];
18
+ /**
19
+ * Applies the react-refresh Babel plugin on non-production modes only
20
+ * Ensure `react-refresh/runtime` is hoisted and shared
21
+ * https://github.com/pmmmwh/react-refresh-webpack-plugin/blob/main/docs/TROUBLESHOOTING.md#externalising-react
22
+ */
23
+ export const devReactFastRefresh = {
24
+ runtime: `reactRefreshRuntime`,
25
+ reactRefreshSetup: `reactRefreshSetup`,
26
+ };
27
+ /**
28
+ * Array of keys to ignore in the verifyGroupEntryOptions step
29
+ */
30
+ export const ignoreEntryOptionKeys = [
31
+ 'title',
32
+ ];
33
+ /**
34
+ * The maximum size of an entry group.
35
+ */
36
+ export const maxEntryGroupSize = 10;
@@ -1 +1,6 @@
1
- import{mergeOptions}from"@flatjs/common";export const createExternals=(t={},e)=>{const o=e[1],r=o.options?.externals||{};return mergeOptions(t,r)};
1
+ import { mergeOptions } from '@flatjs/common';
2
+ export const createExternals = (externals = {}, entryItem) => {
3
+ const entryItemContent = entryItem[1];
4
+ const entryItemExternals = entryItemContent.options?.externals || {};
5
+ return mergeOptions(externals, entryItemExternals);
6
+ };
@@ -1 +1,43 @@
1
- import{join}from"node:path";import{devReactFastRefresh}from"../constants.js";import{shouldEnableReactFastRefresh}from"../helpers/should-enable-react-fast-refresh.js";import{createMinimizers}from"../minimizer/index.js";export const createOptimization=(e,i,n)=>({nodeEnv:e?"development":"production",chunkIds:"named",moduleIds:"named",runtimeChunk:!!shouldEnableReactFastRefresh(e,n,i)&&{name:e=>join(e.name,devReactFastRefresh.runtime)},minimize:!1!==i.webpack?.minimizer&&!e,minimizer:createMinimizers(e,i.webpack),splitChunks:{name:!1,chunks:"all",minSize:25e5,cacheGroups:{default:!1,defaultVendors:!1}}});
1
+ import { join } from 'node:path';
2
+ import { devReactFastRefresh } from '../constants.js';
3
+ import { shouldEnableReactFastRefresh } from '../helpers/should-enable-react-fast-refresh.js';
4
+ import { createMinimizers } from '../minimizer/index.js';
5
+ export const createOptimization = (serveMode, evolveOptions, entryMapItem) => {
6
+ // Indicates current we use `hot` mode for `webpack-dev-server` hot reload true.
7
+ const enabledHmr = shouldEnableReactFastRefresh(serveMode, entryMapItem, evolveOptions);
8
+ const webpackOptimization = {
9
+ nodeEnv: serveMode ? 'development' : 'production',
10
+ chunkIds: 'named',
11
+ moduleIds: 'named',
12
+ // Ensure `react-refresh/runtime` is hoisted and shared, Could be replicated via a vendors chunk
13
+ // NOTE: This is only for `HMR` mode, if we have no `HMR` mode, we should not use this! it always be `false`
14
+ runtimeChunk: enabledHmr
15
+ ? {
16
+ name: (entrypoint) => {
17
+ return join(entrypoint.name, devReactFastRefresh.runtime);
18
+ },
19
+ }
20
+ : false,
21
+ // This is true in production mode. Tell webpack to minimize the bundle using the TerserPlugin
22
+ minimize: evolveOptions.webpack?.minimizer !== false && !serveMode,
23
+ // Note: the `minimizer` will executed must be wait until `minimize` is `true`
24
+ minimizer: createMinimizers(serveMode, evolveOptions.webpack),
25
+ // Disabled WARNING in webpack while chunk exceed the recommended size limit for `serve`
26
+ splitChunks: {
27
+ // It is recommended to set splitChunks.name to false for production builds
28
+ // so that it doesn't change names unnecessarily.
29
+ name: false,
30
+ // include all types of chunks
31
+ // chunks: 'async',
32
+ chunks: 'all',
33
+ // 2.3841858(MB)
34
+ minSize: 2500000,
35
+ // disable vendors~loadsh.js...
36
+ cacheGroups: {
37
+ default: false,
38
+ defaultVendors: false,
39
+ },
40
+ },
41
+ };
42
+ return webpackOptimization;
43
+ };
@@ -1 +1,35 @@
1
- import{join}from"node:path";import{getBundleFileName}from"../helpers/get-bundle-file-name.js";import{resolvePublicPath}from"./resolve-public-path.js";export const createOutput=async(e,t,o)=>{const{projectCwd:n,webpack:a}=t,i=o[1],p=resolvePublicPath(t),u="function"==typeof a?.outputDir?await a.outputDir():a?.outputDir||"public";return{devtoolModuleFilenameTemplate:({namespace:e,resourcePath:t})=>`webpack:///${join(e,t)}`,environment:{},pathinfo:!1,path:join(n,u),publicPath:p,filename:`[name]/${getBundleFileName("js",e,a?.enableBundleHashName)}`,chunkFilename:"[id].[contenthash].js",...i.options?.output}};
1
+ import { join } from 'node:path';
2
+ import { getBundleFileName } from '../helpers/get-bundle-file-name.js';
3
+ import { resolvePublicPath } from './resolve-public-path.js';
4
+ export const createOutput = async (serveMode, evolveOptions, entryItem) => {
5
+ const { projectCwd, webpack } = evolveOptions;
6
+ const entryItemOption = entryItem[1];
7
+ // If we have customized publicPath, should be converted to `https://cdn.example.com/assets/`, `/assets/`
8
+ const publicPath = resolvePublicPath(evolveOptions);
9
+ // Allow us dynamic return `outputDir`, e.g dev_xxxx, we can create built directory via `branchName`
10
+ const outputDir = typeof webpack?.outputDir === 'function'
11
+ ? await webpack.outputDir()
12
+ : webpack?.outputDir || 'public';
13
+ const webpackOutput = {
14
+ // Formatting devtool sourcemap template file.
15
+ devtoolModuleFilenameTemplate: ({ namespace, resourcePath }) => {
16
+ return `webpack:///${join(namespace, resourcePath)}`;
17
+ },
18
+ // Replace output.ecmaVersion with output.environment and more detailed
19
+ environment: {},
20
+ // Include comments with information about the modules, Disable it can improved performance.
21
+ pathinfo: false,
22
+ // The output directory as an absolute path.
23
+ path: join(projectCwd, outputDir),
24
+ // The publicPath specifies the public URL address of the output files when referenced in a browser.
25
+ publicPath,
26
+ // Specifies the name of each output file on disk. You must not specify an absolute path here!
27
+ filename: `[name]/${getBundleFileName('js', serveMode, webpack?.enableBundleHashName)}`,
28
+ // hotUpdateMainFilename: '[runtime].[fullhash].hot-update.json',
29
+ // The filename of non-entry chunks as relative path inside the output.path directory.
30
+ chunkFilename: `[id].[contenthash].js`,
31
+ // Extends / overrides the default output configuration
32
+ ...entryItemOption.options?.output,
33
+ };
34
+ return webpackOutput;
35
+ };
@@ -1 +1,7 @@
1
- export const createPerformance=(n,e={})=>{const r={hints:!n&&"warning"};return Object.assign(r,e)};
1
+ export const createPerformance = (serveMode, performanceOptions = {}) => {
2
+ const basePerformance = {
3
+ // Disable entry size exceeds recommands warning for `serve` mode
4
+ hints: serveMode ? false : 'warning',
5
+ };
6
+ return Object.assign(basePerformance, performanceOptions);
7
+ };
@@ -1 +1,78 @@
1
- import{logger}from"@flatjs/common";import ReactRefreshWebpackPlugin from"@pmmmwh/react-refresh-webpack-plugin";import CaseSensitivePathsPlugin from"case-sensitive-paths-webpack-plugin";import MiniCssExtractPlugin from"mini-css-extract-plugin";import webpack from"webpack";import{BundleAnalyzerPlugin}from"webpack-bundle-analyzer";import{enableBundleHashNameForModule}from"../helpers/enable-bundle-hashname-for-module.js";import{getBundleFileName}from"../helpers/get-bundle-file-name.js";import{shouldEnableReactFastRefresh}from"../helpers/should-enable-react-fast-refresh.js";import{createCircularDependencyPlugin}from"../plugins/circular-dependency/index.js";import{createCleanWebpackPlugin}from"../plugins/clean-webpack/index.js";import{createBuiltinDefineVariables}from"../plugins/define-variable/index.js";import{createModuleFederationPlugin}from"../plugins/module-federation/index.js";import{createHtmlPlugins}from"../plugins/multi-html/index.js";import{createTsCheckerPlugins}from"../plugins/ts-checker/index.js";export const createPlugins=async(e,a,n)=>{const r=a[0],[l,i]=r,s=enableBundleHashNameForModule(n,i?.options),t=[new webpack.WatchIgnorePlugin({paths:[/\.d\.[cm]ts$/]}),new CaseSensitivePathsPlugin,...createCircularDependencyPlugin(e,n),new MiniCssExtractPlugin({filename:`[name]/${getBundleFileName("css",e,s)}`,chunkFilename:"[id].[contenthash].css"}),...await createBuiltinDefineVariables(e,n),...createCleanWebpackPlugin(e,a,n),...createModuleFederationPlugin(e,a,n),...createHtmlPlugins(e,a,n),...createTsCheckerPlugins(e,a,n)];n.analyzer&&t.push(new BundleAnalyzerPlugin({analyzerPort:"auto",analyzerMode:"server",...n.analyzer}));const o=shouldEnableReactFastRefresh(e,r,n);o&&t.push(new ReactRefreshWebpackPlugin({overlay:!1})),!o&&e&&(n.devServer?.liveReload?logger.warn('The HMR disabled cause of "liveReload" specificed'):logger.warn(`The HMR disabled cause of \`"moduleFederation":"${l}"\``));const c=n.webpack?.plugins||[];return t.concat(c)};
1
+ import { logger } from '@flatjs/common';
2
+ import ReactRefreshWebpackPlugin from '@pmmmwh/react-refresh-webpack-plugin';
3
+ import CaseSensitivePathsPlugin from 'case-sensitive-paths-webpack-plugin';
4
+ import MiniCssExtractPlugin from 'mini-css-extract-plugin';
5
+ import webpack from 'webpack';
6
+ import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer';
7
+ import { enableBundleHashNameForModule } from '../helpers/enable-bundle-hashname-for-module.js';
8
+ import { getBundleFileName } from '../helpers/get-bundle-file-name.js';
9
+ import { shouldEnableReactFastRefresh } from '../helpers/should-enable-react-fast-refresh.js';
10
+ import { createCircularDependencyPlugin } from '../plugins/circular-dependency/index.js';
11
+ import { createCleanWebpackPlugin } from '../plugins/clean-webpack/index.js';
12
+ import { createBuiltinDefineVariables } from '../plugins/define-variable/index.js';
13
+ import { createModuleFederationPlugin } from '../plugins/module-federation/index.js';
14
+ import { createHtmlPlugins } from '../plugins/multi-html/index.js';
15
+ import { createTsCheckerPlugins } from '../plugins/ts-checker/index.js';
16
+ export const createPlugins = async (serveMode, entryMapItemList, evolveOptions) => {
17
+ const firstEntryMapItem = entryMapItemList[0];
18
+ const [entryName, entryItemOption] = firstEntryMapItem;
19
+ const bundleHashNameEnabled = enableBundleHashNameForModule(evolveOptions, entryItemOption?.options);
20
+ const builtInPlugins = [
21
+ // Because TS will may generate .js and .d.ts files, you should ignore these files,
22
+ // otherwise watchers may go into an infinite watch loop.
23
+ new webpack.WatchIgnorePlugin({
24
+ paths: [/\.d\.[cm]ts$/],
25
+ }),
26
+ // Case Sensitive Paths for OSX
27
+ new CaseSensitivePathsPlugin(),
28
+ // Detect modules with circular dependencies when bundling with webpack for `development` mode.
29
+ ...createCircularDependencyPlugin(serveMode, evolveOptions),
30
+ // For css minify extractor, Note `"sideEffects": false,` of `package.json` will not emits a file (writes a file to the filesystem)
31
+ new MiniCssExtractPlugin({
32
+ // Options similar to the same options in webpackOptions.output
33
+ // both options are optional
34
+ filename: `[name]/${getBundleFileName('css', serveMode, bundleHashNameEnabled)}`,
35
+ // the chunkFilename option can be a function for webpack@5
36
+ chunkFilename: '[id].[contenthash].css',
37
+ }),
38
+ // create builtin DefinePlugin
39
+ ...(await createBuiltinDefineVariables(serveMode, evolveOptions)),
40
+ // clean webpack plugin
41
+ ...createCleanWebpackPlugin(serveMode, entryMapItemList, evolveOptions),
42
+ // Put ModuleFederationPlugin before html webpack plugin.
43
+ ...createModuleFederationPlugin(serveMode, entryMapItemList, evolveOptions),
44
+ // Create all need html plugins
45
+ ...createHtmlPlugins(serveMode, entryMapItemList, evolveOptions),
46
+ // Create all need ts-checker plugins
47
+ ...createTsCheckerPlugins(serveMode, entryMapItemList, evolveOptions),
48
+ ];
49
+ // Analyze an existing bundle, if allowed.
50
+ if (evolveOptions.analyzer) {
51
+ builtInPlugins.push(new BundleAnalyzerPlugin({
52
+ analyzerPort: 'auto',
53
+ analyzerMode: 'server',
54
+ ...evolveOptions.analyzer,
55
+ }));
56
+ }
57
+ // Indicates current we use `hot` mode for `webpack-dev-server` hot reload true.
58
+ const enabledHmr = shouldEnableReactFastRefresh(serveMode, firstEntryMapItem, evolveOptions);
59
+ if (enabledHmr) {
60
+ // Applies the react-refresh Babel plugin on non-production modes only
61
+ // Ensure `react-refresh/runtime` is hoisted and shared
62
+ // https://github.com/pmmmwh/react-refresh-webpack-plugin/blob/main/docs/TROUBLESHOOTING.md#externalising-react
63
+ builtInPlugins.push(new ReactRefreshWebpackPlugin({
64
+ // Always use webpack-dev-server `client` overlay!
65
+ overlay: false,
66
+ }));
67
+ }
68
+ if (!enabledHmr && serveMode) {
69
+ if (evolveOptions.devServer?.liveReload) {
70
+ logger.warn(`The HMR disabled cause of "liveReload" specificed`);
71
+ }
72
+ else {
73
+ logger.warn(`The HMR disabled cause of \`"moduleFederation":"${entryName}"\``);
74
+ }
75
+ }
76
+ const extraPlugins = evolveOptions.webpack?.plugins || [];
77
+ return builtInPlugins.concat(extraPlugins);
78
+ };
@@ -1 +1,37 @@
1
- import{join}from"node:path";import{mergeOptions}from"@flatjs/common";import{TsconfigPathsPlugin}from"tsconfig-paths-webpack-plugin";export const createResolve=(s,o)=>{const n={mainFields:["browser","module","main"],extensions:[".ts",".tsx",".js",".json"],extensionAlias:{".js":[".js",".ts"],".cjs":[".cjs",".cts"],".mjs":[".mjs",".mts"],".jsx":[".jsx",".tsx"]},plugins:[new TsconfigPathsPlugin({configFile:join(s,"tsconfig.json"),extensions:[".ts",".tsx",".js",".jsx"]})]};return mergeOptions(n,o?.resolve||{})};
1
+ /* eslint-disable @typescript-eslint/naming-convention */
2
+ import { join } from 'node:path';
3
+ import { mergeOptions } from '@flatjs/common';
4
+ import { TsconfigPathsPlugin } from 'tsconfig-paths-webpack-plugin';
5
+ export const createResolve = (projectCwd, webpackOptions) => {
6
+ const resolve = {
7
+ mainFields: ['browser', 'module', 'main'],
8
+ // Add `.ts` and `.tsx` as a resolvable extension.
9
+ extensions: ['.ts', '.tsx', '.js', '.json'],
10
+ // Add support for TypeScripts fully qualified ESM imports.
11
+ extensionAlias: {
12
+ '.js': ['.js', '.ts'],
13
+ '.cjs': ['.cjs', '.cts'],
14
+ '.mjs': ['.mjs', '.mts'],
15
+ '.jsx': ['.jsx', '.tsx'],
16
+ },
17
+ plugins: [
18
+ // Resolve modules according to baseUrl and paths in your tsconfig.json.
19
+ // https://www.npmjs.com/package/tsconfig-paths-webpack-plugin
20
+ // FIXME: Don't support `moduleResolution:nodenext`, for now support `moduleResolution:node`
21
+ // All alias import don't include suffix e.g. `.js`
22
+ // 1. correct `import { x } from '@/utils/str`
23
+ // 2. wrong `import { x } from '@/utils/str.js`
24
+ // 3. it will also help `less-loader` to support `@import` directly no additional `resolve.alias` setup
25
+ // @import '~@/utils/xxx.less'
26
+ // @import url('./child.less');
27
+ // @import url('~@/react/less/alias.less');
28
+ // @import '~@/react/less/alias2.less';
29
+ // @import '~@/utils/shared.less';
30
+ new TsconfigPathsPlugin({
31
+ configFile: join(projectCwd, 'tsconfig.json'),
32
+ extensions: ['.ts', '.tsx', '.js', '.jsx'],
33
+ }),
34
+ ],
35
+ };
36
+ return mergeOptions(resolve, webpackOptions?.resolve || {});
37
+ };
@@ -1 +1,20 @@
1
- import{ruleAssets}from"./rule-sets/rule-assets.js";import{ruleCss}from"./rule-sets/rule-css.js";import{ruleLess}from"./rule-sets/rule-less.js";import{ruleScripts}from"./rule-sets/rule-scripts.js";import{ruleSvgIcon}from"./rule-sets/rule-svg-icon.js";export const createRuleSets=(s,e,r)=>{const l=e[0],t=[ruleSvgIcon(),ruleAssets(e,r),ruleCss(s,l,r,!1),ruleCss(s,l,r,!0),ruleLess(s,l,r),ruleScripts(s,l,r)],u=r.webpack?.ruleSets||[];return t.concat(u)};
1
+ import { ruleAssets } from './rule-sets/rule-assets.js';
2
+ import { ruleCss } from './rule-sets/rule-css.js';
3
+ import { ruleLess } from './rule-sets/rule-less.js';
4
+ import { ruleScripts } from './rule-sets/rule-scripts.js';
5
+ import { ruleSvgIcon } from './rule-sets/rule-svg-icon.js';
6
+ export const createRuleSets = (serveMode, entryMapItemList, evolveOptions) => {
7
+ const entryMapItem = entryMapItemList[0];
8
+ const rules = [
9
+ ruleSvgIcon(),
10
+ ruleAssets(entryMapItemList, evolveOptions),
11
+ // normal css style.
12
+ ruleCss(serveMode, entryMapItem, evolveOptions, false),
13
+ // css module style. xxx.module.css
14
+ ruleCss(serveMode, entryMapItem, evolveOptions, true),
15
+ ruleLess(serveMode, entryMapItem, evolveOptions),
16
+ ruleScripts(serveMode, entryMapItem, evolveOptions),
17
+ ];
18
+ const extraRuleSets = evolveOptions.webpack?.ruleSets || [];
19
+ return rules.concat(extraRuleSets);
20
+ };
@@ -1 +1,57 @@
1
- import{assertGroupEntryItem}from"../helpers/assert-group-entry-item.js";import{createExternals}from"./create-externals.js";import{createOptimization}from"./create-optimization.js";import{createOutput}from"./create-output.js";import{createPerformance}from"./create-performance.js";import{createPlugins}from"./create-plugins.js";import{createResolve}from"./create-resolve.js";import{createRuleSets}from"./create-rule-sets.js";export const loadWebpackConfig=async(e,t,r)=>{const a="development"===e,{projectCwd:o,webpack:s,devServer:c}=r,n=c?.watchOptions,p=assertGroupEntryItem(t,r),i=createRuleSets(a,p,r),m=await createPlugins(a,p,r),l=p[0];return{mode:e,plugins:m,watchOptions:n,output:await createOutput(a,r,l),context:o,target:s?.target??["web","es5"],resolve:createResolve(o,s),module:{rules:i},devtool:a?"eval-source-map":s?.sourceMap||!1,externalsType:s?.externalsType,externals:createExternals(s?.externals,l),performance:createPerformance(a,s?.performance),optimization:createOptimization(a,r,l),infrastructureLogging:s?.infrastructureLogging??{level:"warn"},stats:s?.stats??{preset:"minimal"},cache:{type:"memory"}}};
1
+ import { assertGroupEntryItem } from '../helpers/assert-group-entry-item.js';
2
+ import { createExternals } from './create-externals.js';
3
+ import { createOptimization } from './create-optimization.js';
4
+ import { createOutput } from './create-output.js';
5
+ import { createPerformance } from './create-performance.js';
6
+ import { createPlugins } from './create-plugins.js';
7
+ import { createResolve } from './create-resolve.js';
8
+ import { createRuleSets } from './create-rule-sets.js';
9
+ /**
10
+ * Try to organization the configuraiton object of `webpack`
11
+ * @param mode Enable production optimizations or development hints.
12
+ * @param entryMap The only single one `servedEntry` or `toBuildEntry`
13
+ * @param overrideOptions The manually override configuration options for flatjsEvolve
14
+ */
15
+ export const loadWebpackConfig = async (mode, entryMap, evolveOptions) => {
16
+ const serveMode = mode === 'development';
17
+ const { projectCwd, webpack, devServer } = evolveOptions;
18
+ const watchOptions = devServer?.watchOptions;
19
+ const entryMapItemList = assertGroupEntryItem(entryMap, evolveOptions);
20
+ const moduleRules = createRuleSets(serveMode, entryMapItemList, evolveOptions);
21
+ const plugins = await createPlugins(serveMode, entryMapItemList, evolveOptions);
22
+ const firstEntryMap = entryMapItemList[0];
23
+ const output = await createOutput(serveMode, evolveOptions, firstEntryMap);
24
+ const webpackConfig = {
25
+ mode,
26
+ plugins,
27
+ watchOptions,
28
+ output,
29
+ // The base directory, an absolute path, for resolving entry points and loaders from configuration.
30
+ // The context is an absolute string to the directory that contains the entry files.
31
+ context: projectCwd,
32
+ target: webpack?.target ?? ['web', 'es5'],
33
+ resolve: createResolve(projectCwd, webpack),
34
+ module: { rules: moduleRules },
35
+ devtool: serveMode ? 'eval-source-map' : webpack?.sourceMap || false,
36
+ externalsType: webpack?.externalsType,
37
+ // It's globally external configurations for all entries, if we need to specificed externals for each entry.
38
+ // Simply move it into entry options.
39
+ externals: createExternals(webpack?.externals, firstEntryMap),
40
+ performance: createPerformance(serveMode, webpack?.performance),
41
+ optimization: createOptimization(serveMode, evolveOptions, firstEntryMap),
42
+ // Setup logging level for `infrastructure` like. `webpack-dev-server`
43
+ infrastructureLogging: webpack?.infrastructureLogging ?? {
44
+ level: 'warn',
45
+ },
46
+ stats: webpack?.stats ?? {
47
+ preset: 'minimal',
48
+ },
49
+ cache: {
50
+ // Use `filesystem` cache to improve performance for `production` build
51
+ // Default cache directory is `node_modules/.cache`
52
+ // type: serveMode ? 'memory' : 'filesystem',
53
+ type: 'memory',
54
+ },
55
+ };
56
+ return webpackConfig;
57
+ };
@@ -1 +1,15 @@
1
- import{ensureSlash}from"@flatjs/common";export const resolvePublicPath=t=>{const{webpack:a}=t;let e="auto";return a?.publicPath&&"auto"!==a.publicPath&&(e=ensureSlash(a.publicPath,!0)),e};
1
+ import { ensureSlash } from '@flatjs/common';
2
+ /**
3
+ * Try to normalize publicPath, if we have customized publicPath, should be converted to `https://cdn.example.com/assets/`, `/assets/`
4
+ * @param evolveOptions
5
+ * @returns `auto` or customizd publicPath
6
+ */
7
+ export const resolvePublicPath = (evolveOptions) => {
8
+ const { webpack } = evolveOptions;
9
+ let publicPath = 'auto';
10
+ // If we have customized publicPath, should be converted to `https://cdn.example.com/assets/`, `/assets/`
11
+ if (webpack?.publicPath && webpack.publicPath !== 'auto') {
12
+ publicPath = ensureSlash(webpack.publicPath, true);
13
+ }
14
+ return publicPath;
15
+ };
@@ -1 +1,3 @@
1
- export const ICON_PATH_REGEX=/svg-icons\//;export const IMAGE_PATH_REGEX=/\.(?:jpe?g|png|gif|svg)$/;export const FONT_PATH_REGEX=/\.(?:ttf|eot|woff|woff2)(?:\?.+)?$/;
1
+ export const ICON_PATH_REGEX = /svg-icons\//;
2
+ export const IMAGE_PATH_REGEX = /\.(?:jpe?g|png|gif|svg)$/;
3
+ export const FONT_PATH_REGEX = /\.(?:ttf|eot|woff|woff2)(?:\?.+)?$/;
@@ -1 +1,52 @@
1
- import{dirname,join,relative,resolve}from"node:path";import{resolvePublicPath}from"../resolve-public-path.js";import{FONT_PATH_REGEX,IMAGE_PATH_REGEX}from"./constants.js";import{isIconSvg}from"./rule-utils.js";const getEntryAssetFileName=(e,t,r)=>{for(const o of t){const[t,s]=o,{projectCwd:a,projectVirtualPath:i}=r;let n=dirname(join(i,e.replace(/^src/,"")));const l=s.entry.map((e=>dirname(join(a,e)))),m=resolve(a,e),c=l.find((e=>m.startsWith(e)));return c&&(n=dirname(join(t,relative(c,m)))),`${n}/[name]-[contenthash:8][ext]`}};export const ruleAssets=(e,t)=>{const r=resolvePublicPath(t);return{type:"asset",test:e=>FONT_PATH_REGEX.test(e)||IMAGE_PATH_REGEX.test(e)&&!isIconSvg(e),generator:{filename:({filename:r})=>getEntryAssetFileName(r,e,t),publicPath:"auto"===r?void 0:r},parser:{dataUrlCondition:{maxSize:t.loaderOptions.assetDataUrlMaxSize}}}};
1
+ import { dirname, join, relative, resolve } from 'node:path';
2
+ import { resolvePublicPath } from '../resolve-public-path.js';
3
+ import { FONT_PATH_REGEX, IMAGE_PATH_REGEX } from './constants.js';
4
+ import { isIconSvg } from './rule-utils.js';
5
+ const getEntryAssetFileName = (filename, entryMapItemList, evolveOptions) => {
6
+ for (const entryMapItem of entryMapItemList) {
7
+ const [entryName, entryConfig] = entryMapItem;
8
+ const { projectCwd, projectVirtualPath } = evolveOptions;
9
+ let assetBase = dirname(join(projectVirtualPath, filename.replace(/^src/, '')));
10
+ const entryDirs = entryConfig.entry.map((file) => dirname(join(projectCwd, file)));
11
+ const assetAbsName = resolve(projectCwd, filename);
12
+ const matchedEntryDir = entryDirs.find((s) => assetAbsName.startsWith(s));
13
+ if (matchedEntryDir) {
14
+ assetBase = dirname(join(entryName, relative(matchedEntryDir, assetAbsName)));
15
+ }
16
+ return `${assetBase}/[name]-[contenthash:8][ext]`;
17
+ }
18
+ };
19
+ /**
20
+ * Preparing image loader for normal pictures except stored in folder `icons`
21
+ * Webpack@5 don't need `file-loader`, `raw-loader`, `url-loader` provider us `asset-modules`
22
+ * https://webpack.js.org/guides/asset-modules/
23
+ * @param entryMapItemList The available entries, `development` it contains multiple enties, `production`
24
+ */
25
+ export const ruleAssets = (entryMapItemList, evolveOptions) => {
26
+ // If we have customized publicPath, should be converted to `https://cdn.example.com/assets/`, `/assets/`
27
+ const publicPath = resolvePublicPath(evolveOptions);
28
+ const loader = {
29
+ type: 'asset',
30
+ test(resource) {
31
+ return (FONT_PATH_REGEX.test(resource) ||
32
+ (IMAGE_PATH_REGEX.test(resource) && !isIconSvg(resource)));
33
+ },
34
+ generator: {
35
+ // Rule.generator.filename is the same as output.assetModuleFilename and works only with asset and asset/resource module types.
36
+ filename({ filename }) {
37
+ return getEntryAssetFileName(filename, entryMapItemList, evolveOptions);
38
+ },
39
+ // Make sure that we use production cdn for images avoid use `requireExtensions`
40
+ // NOTE: if `auto` we need to remove `publicPath` configuration leave it to undefined.
41
+ publicPath: publicPath === 'auto' ? undefined : publicPath,
42
+ },
43
+ parser: {
44
+ // Now webpack will automatically choose between resource and inline by following
45
+ // a default condition: a file with size less than 8kb will be treated as a inline module type and resource module type otherwise.
46
+ dataUrlCondition: {
47
+ maxSize: evolveOptions.loaderOptions.assetDataUrlMaxSize, // 4 * 1024, // 4kb
48
+ },
49
+ },
50
+ };
51
+ return loader;
52
+ };
@@ -1 +1,111 @@
1
- import{requireResolve}from"@flatjs/common";import{forgePostcssPluginPixel}from"@flatjs/forge-postcss-plugin-pixel";import cssnano from"cssnano";import MiniCssExtractPlugin from"mini-css-extract-plugin";import{allowPx2remForModule}from"../../helpers/allow-px2rem-for-module.js";const getPostcssOptions=(s,o={},e={})=>{const r=[...e.plugins||[],cssnano({preset:["default",{discardComments:{removeAll:!s},reduceInitial:!1,normalizeWhitespace:!s,...e.cssnanoOptions}]})];return!1!==o&&r.push(forgePostcssPluginPixel(o)),{plugins:r}};export const ruleCss=(s,o,e,r=!1)=>{const{pixelOptions:t,cssLoaderOptions:i={},postcssOptions:l}=e.loaderOptions,n=r?{}:{modules:!1},p={test:/\.css$/i,use:[{loader:MiniCssExtractPlugin.loader,options:{esModule:!0}},{loader:requireResolve(import.meta.url,"css-loader"),options:{sourceMap:s,...i,...n}}]};r?p.include=/\.module\.css$/i:p.exclude=/\.module\.css$/i;const c=allowPx2remForModule(o,e);if(Array.isArray(p.use)){const o=getPostcssOptions(s,!!c&&t,l);p.use.push({loader:requireResolve(import.meta.url,"postcss-loader"),options:{postcssOptions:{...o,config:!1},sourceMap:s}})}return p};
1
+ import { requireResolve } from '@flatjs/common';
2
+ import { forgePostcssPluginPixel, } from '@flatjs/forge-postcss-plugin-pixel';
3
+ import cssnano from 'cssnano';
4
+ import MiniCssExtractPlugin from 'mini-css-extract-plugin';
5
+ import { allowPx2remForModule } from '../../helpers/allow-px2rem-for-module.js';
6
+ /**
7
+ * Normalize postcss-loader options.
8
+ * @param serveMode The value indicates if we are in `built` or `serve` mode.
9
+ * @param pixelOptions The pixel options of `postcss` plugin
10
+ * @param cssnanoOptions The configuration rules for `cssnano`
11
+ */
12
+ const getPostcssOptions = (serveMode, pixelOptions = {}, postcssOptions = {}) => {
13
+ // Use cssnano to minify css styles.
14
+ // https://cssnano.co/docs/config-file
15
+ const postCssPlugins = [
16
+ ...(postcssOptions.plugins || []),
17
+ cssnano({
18
+ // https://www.npmjs.com/package/cssnano-preset-default
19
+ // Note Advanced optimisations for cssnano; may or may not break your CSS!
20
+ // `Antd` was broken while use `advanced` preset.:(
21
+ preset: [
22
+ 'default',
23
+ {
24
+ discardComments: {
25
+ removeAll: !serveMode,
26
+ },
27
+ // throw new error `Please provide a proper feature name. Cannot find css-initial-value`
28
+ // disable this plugin `postcss-reduce-initial` via reduceInitial: false
29
+ // disable this plugin `postcss-minify-font-values` via minifyFontValues:false
30
+ reduceInitial: false,
31
+ // minifyFontValues: false,
32
+ normalizeWhitespace: !serveMode,
33
+ // allow us override cssnano configuration rules.
34
+ ...postcssOptions.cssnanoOptions,
35
+ },
36
+ ],
37
+ }),
38
+ ];
39
+ if (pixelOptions !== false) {
40
+ postCssPlugins.push(forgePostcssPluginPixel(pixelOptions));
41
+ }
42
+ return {
43
+ plugins: postCssPlugins,
44
+ };
45
+ };
46
+ /**
47
+ * Actually, style-loader is the one that is responsible for CSS HMR
48
+ * https://github.com/webpack-contrib/style-loader/blob/master/src/index.js#L31-L42
49
+ * @param serveMode
50
+ * @param entryMapItem
51
+ * @param evolveOptions `builtin` loaders
52
+ */
53
+ export const ruleCss = (serveMode, entryMapItem, evolveOptions, useCssModule = false) => {
54
+ // The value indicates we will enable px2rem using `@flatjs/forge-postcss-plugin-pixel`
55
+ const { pixelOptions, cssLoaderOptions = {}, postcssOptions, } = evolveOptions.loaderOptions;
56
+ const { modules, ...restCssLoaderOptions } = cssLoaderOptions;
57
+ // automatically enable css modules for files with .module.css extension
58
+ const cssLoaderOfCssModules = !useCssModule
59
+ ? { modules: false }
60
+ : {
61
+ modules: Object.assign({
62
+ // keep empty to allow user customized css modules options.
63
+ // Depends on the value of the esModule option. If the value of the esModule options is true, this value will also be true, otherwise it will be false.
64
+ // For now give default value `false` to allow import css module via `import styles from './stye.module.css'`, if we want to use named exports we can set it to `true` via `flatjs-evolve.config.ts`
65
+ namedExport: false,
66
+ }, modules),
67
+ };
68
+ const ruleSet = {
69
+ test: /\.css$/i,
70
+ use: [
71
+ {
72
+ loader: MiniCssExtractPlugin.loader,
73
+ options: {
74
+ // https://github.com/webpack-contrib/mini-css-extract-plugin/releases/tag/v1.0.0
75
+ // https://github.com/webpack-contrib/css-loader/blob/master/README.md#modules
76
+ esModule: true,
77
+ },
78
+ },
79
+ {
80
+ loader: requireResolve(import.meta.url, 'css-loader'),
81
+ options: {
82
+ sourceMap: serveMode,
83
+ ...cssLoaderOfCssModules,
84
+ ...restCssLoaderOptions,
85
+ },
86
+ },
87
+ ],
88
+ };
89
+ if (useCssModule) {
90
+ ruleSet.include = /\.module\.css$/i;
91
+ }
92
+ else {
93
+ ruleSet.exclude = /\.module\.css$/i;
94
+ }
95
+ const isAllowPx2Rem = allowPx2remForModule(entryMapItem, evolveOptions);
96
+ if (Array.isArray(ruleSet.use)) {
97
+ const postCssOption = getPostcssOptions(serveMode, isAllowPx2Rem ? pixelOptions : false, postcssOptions);
98
+ ruleSet.use.push({
99
+ loader: requireResolve(import.meta.url, 'postcss-loader'),
100
+ options: {
101
+ postcssOptions: {
102
+ ...postCssOption,
103
+ // Removes the need to lookup and load external config files ( `postcss.config.cjs`...) multiple times during compilation.
104
+ config: false,
105
+ },
106
+ sourceMap: serveMode,
107
+ },
108
+ });
109
+ }
110
+ return ruleSet;
111
+ };
@@ -1 +1,44 @@
1
- import{requireResolve}from"@flatjs/common";import{ruleCss}from"./rule-css.js";export const ruleLess=(s,e,r)=>{const o=ruleCss(s,e,r);o.test=/\.less$/i;const t=r.loaderOptions.lessOptions;return Array.isArray(o.use)&&o.use.push({loader:requireResolve(import.meta.url,"less-loader"),options:{sourceMap:s,lessOptions:{sourceMap:s,javascriptEnabled:!0,...t}}}),o};
1
+ import { requireResolve } from '@flatjs/common';
2
+ import { ruleCss } from './rule-css.js';
3
+ /**
4
+ * Preparing configurations for `less-loader`
5
+ * @param serveMode The value indicates if we are in `built` or `serve` mode.
6
+ * @param pluginLoaderOptions `builtin` loaders
7
+ * @example
8
+ * ```ts
9
+ * `~` makes the url an module
10
+ * webpack: {
11
+ * externals: {
12
+ * antd: 'antd',
13
+ * dayjs: 'dayjs',
14
+ * },
15
+ * resolve: {
16
+ * alias: {
17
+ * '@': resolve(projectCwd, './src'),
18
+ * },
19
+ * },
20
+ * },
21
+ * `@import '~@/theme/default.less';` at `src/theme/default.less`
22
+ *
23
+ * ```
24
+ */
25
+ export const ruleLess = (serveMode, entryMapItem, evolveOptions) => {
26
+ const ruleSet = ruleCss(serveMode, entryMapItem, evolveOptions);
27
+ ruleSet.test = /\.less$/i;
28
+ // The Options for Less.
29
+ const lessOptions = evolveOptions.loaderOptions.lessOptions;
30
+ if (Array.isArray(ruleSet.use)) {
31
+ ruleSet.use.push({
32
+ loader: requireResolve(import.meta.url, 'less-loader'),
33
+ options: {
34
+ sourceMap: serveMode,
35
+ lessOptions: {
36
+ sourceMap: serveMode,
37
+ javascriptEnabled: true,
38
+ ...lessOptions,
39
+ },
40
+ },
41
+ });
42
+ }
43
+ return ruleSet;
44
+ };
@@ -1 +1,34 @@
1
- import{requireResolve}from"@flatjs/common";import{mergeBabelOption}from"../../helpers/merge-babel-options.js";import{shouldEnableReactFastRefresh}from"../../helpers/should-enable-react-fast-refresh.js";export const ruleScripts=(e,r,s)=>{const{babelOptions:o={},modularImports:t=[]}=s.loaderOptions,l=mergeBabelOption(t,o);shouldEnableReactFastRefresh(e,r,s)&&(l.plugins?l.plugins.push(requireResolve(import.meta.url,"react-refresh/babel")):l.plugins=[requireResolve(import.meta.url,"react-refresh/babel")]);return{test:/\.(tsx|ts|js|jsx)$/,use:[{loader:requireResolve(import.meta.url,"babel-loader"),options:l}]}};
1
+ import { requireResolve } from '@flatjs/common';
2
+ import { mergeBabelOption } from '../../helpers/merge-babel-options.js';
3
+ import { shouldEnableReactFastRefresh } from '../../helpers/should-enable-react-fast-refresh.js';
4
+ export const ruleScripts = (serveMode, entryMapItem, evolveOptions) => {
5
+ const { babelOptions = {}, modularImports = [] } = evolveOptions.loaderOptions;
6
+ const finnalBabelOptions = mergeBabelOption(modularImports, babelOptions);
7
+ // Indicates current we use `hot` mode for `webpack-dev-server` hot reload true.
8
+ const enabledHmr = shouldEnableReactFastRefresh(serveMode, entryMapItem, evolveOptions);
9
+ // 针对react 自动注入`react-refresh/babel`
10
+ if (enabledHmr) {
11
+ if (finnalBabelOptions.plugins) {
12
+ finnalBabelOptions.plugins.push(requireResolve(import.meta.url, 'react-refresh/babel'));
13
+ }
14
+ else {
15
+ finnalBabelOptions.plugins = [
16
+ requireResolve(import.meta.url, 'react-refresh/babel'),
17
+ ];
18
+ }
19
+ }
20
+ const loader = {
21
+ // use `vue-loader` to handle .vue here.
22
+ // test: /\.(tsx|ts|js|jsx|vue)$/,
23
+ test: /\.(tsx|ts|js|jsx)$/,
24
+ // Don't exclude anythings because of we need to import node_modules from `@flatjs`
25
+ // exclude: /(node_modules|bower_components)/,
26
+ use: [
27
+ {
28
+ loader: requireResolve(import.meta.url, 'babel-loader'),
29
+ options: finnalBabelOptions,
30
+ },
31
+ ],
32
+ };
33
+ return loader;
34
+ };