mirror of https://github.com/alibaba/ice.git
fix: use built-in split chunks strategy by default (#6699)
* fix: use built-in split chunks strategy by default * fix: pre bundle react refresh package * fix: lint error
This commit is contained in:
parent
7d193fe96b
commit
dd149e51d9
|
@ -0,0 +1,299 @@
|
|||
"use strict";
|
||||
/**
|
||||
* The following code is modified based on the dist build of @rspack/core
|
||||
*/
|
||||
/**
|
||||
* The following code is modified based on
|
||||
* https://github.com/webpack/webpack/blob/4b4ca3b/lib/config/normalization.js
|
||||
*
|
||||
* MIT Licensed
|
||||
* Author Tobias Koppers @sokra
|
||||
* Copyright (c) JS Foundation and other contributors
|
||||
* https://github.com/webpack/webpack/blob/main/LICENSE
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.getNormalizedRspackOptions = void 0;
|
||||
const util_1 = require("../util");
|
||||
const getNormalizedRspackOptions = (config) => {
|
||||
return {
|
||||
features: config.features,
|
||||
ignoreWarnings: config.ignoreWarnings !== undefined
|
||||
? config.ignoreWarnings.map(ignore => {
|
||||
if (typeof ignore === "function") {
|
||||
return ignore;
|
||||
}
|
||||
else {
|
||||
return (warning) => {
|
||||
return ignore.test(warning.message);
|
||||
};
|
||||
}
|
||||
})
|
||||
: undefined,
|
||||
name: config.name,
|
||||
dependencies: config.dependencies,
|
||||
context: config.context,
|
||||
mode: config.mode,
|
||||
entry: config.entry === undefined
|
||||
? { main: {} }
|
||||
: getNormalizedEntryStatic(config.entry),
|
||||
output: nestedConfig(config.output, output => {
|
||||
const { library } = output;
|
||||
const libraryAsName = library;
|
||||
const libraryBase = typeof library === "object" &&
|
||||
library &&
|
||||
!Array.isArray(library) &&
|
||||
"type" in library
|
||||
? library
|
||||
: libraryAsName || output.libraryTarget
|
||||
? {
|
||||
name: libraryAsName
|
||||
}
|
||||
: undefined;
|
||||
// DEPRECATE: remove this in after version
|
||||
{
|
||||
const ext = "[ext]";
|
||||
const filenames = [
|
||||
"filename",
|
||||
"chunkFilename",
|
||||
"cssFilename",
|
||||
"cssChunkFilename"
|
||||
];
|
||||
const checkFilename = (prop) => {
|
||||
const oldFilename = output[prop];
|
||||
if (typeof oldFilename === "string" && oldFilename.endsWith(ext)) {
|
||||
const newFilename = oldFilename.slice(0, -ext.length) +
|
||||
(prop.includes("css") ? ".css" : ".js");
|
||||
(0, util_1.deprecatedWarn)(`Deprecated: output.${prop} ends with [ext] is now deprecated, please use ${newFilename} instead.`);
|
||||
output[prop] = newFilename;
|
||||
}
|
||||
};
|
||||
filenames.forEach(checkFilename);
|
||||
}
|
||||
return {
|
||||
path: output.path,
|
||||
publicPath: output.publicPath,
|
||||
filename: output.filename,
|
||||
clean: output.clean,
|
||||
chunkFormat: output.chunkFormat,
|
||||
chunkLoading: output.chunkLoading,
|
||||
chunkFilename: output.chunkFilename,
|
||||
crossOriginLoading: output.crossOriginLoading,
|
||||
cssFilename: output.cssFilename,
|
||||
cssChunkFilename: output.cssChunkFilename,
|
||||
hotUpdateMainFilename: output.hotUpdateMainFilename,
|
||||
hotUpdateChunkFilename: output.hotUpdateChunkFilename,
|
||||
hotUpdateGlobal: output.hotUpdateGlobal,
|
||||
assetModuleFilename: output.assetModuleFilename,
|
||||
wasmLoading: output.wasmLoading,
|
||||
enabledChunkLoadingTypes: output.enabledChunkLoadingTypes
|
||||
? [...output.enabledChunkLoadingTypes]
|
||||
: ["..."],
|
||||
enabledWasmLoadingTypes: output.enabledWasmLoadingTypes
|
||||
? [...output.enabledWasmLoadingTypes]
|
||||
: ["..."],
|
||||
webassemblyModuleFilename: output.webassemblyModuleFilename,
|
||||
uniqueName: output.uniqueName,
|
||||
chunkLoadingGlobal: output.chunkLoadingGlobal,
|
||||
enabledLibraryTypes: output.enabledLibraryTypes
|
||||
? [...output.enabledLibraryTypes]
|
||||
: ["..."],
|
||||
globalObject: output.globalObject,
|
||||
importFunctionName: output.importFunctionName,
|
||||
iife: output.iife,
|
||||
module: output.module,
|
||||
sourceMapFilename: output.sourceMapFilename,
|
||||
library: libraryBase && {
|
||||
type: output.libraryTarget !== undefined
|
||||
? output.libraryTarget
|
||||
: libraryBase.type,
|
||||
auxiliaryComment: output.auxiliaryComment !== undefined
|
||||
? output.auxiliaryComment
|
||||
: libraryBase.auxiliaryComment,
|
||||
amdContainer: output.amdContainer !== undefined
|
||||
? output.amdContainer
|
||||
: libraryBase.amdContainer,
|
||||
export: output.libraryExport !== undefined
|
||||
? output.libraryExport
|
||||
: libraryBase.export,
|
||||
name: libraryBase.name,
|
||||
umdNamedDefine: output.umdNamedDefine !== undefined
|
||||
? output.umdNamedDefine
|
||||
: libraryBase.umdNamedDefine
|
||||
},
|
||||
trustedTypes: optionalNestedConfig(output.trustedTypes, trustedTypes => {
|
||||
if (trustedTypes === true)
|
||||
return {};
|
||||
if (typeof trustedTypes === "string")
|
||||
return { policyName: trustedTypes };
|
||||
return { ...trustedTypes };
|
||||
}),
|
||||
hashDigest: output.hashDigest,
|
||||
hashDigestLength: output.hashDigestLength,
|
||||
hashFunction: output.hashFunction,
|
||||
hashSalt: output.hashSalt,
|
||||
asyncChunks: output.asyncChunks,
|
||||
workerChunkLoading: output.workerChunkLoading,
|
||||
workerWasmLoading: output.workerWasmLoading,
|
||||
workerPublicPath: output.workerPublicPath
|
||||
};
|
||||
}),
|
||||
resolve: nestedConfig(config.resolve, resolve => ({
|
||||
...resolve
|
||||
})),
|
||||
resolveLoader: nestedConfig(config.resolveLoader, resolve => ({
|
||||
...resolve
|
||||
})),
|
||||
module: nestedConfig(config.module, module => ({
|
||||
parser: keyedNestedConfig(module.parser, cloneObject, {}),
|
||||
generator: keyedNestedConfig(module.generator, cloneObject, {}),
|
||||
defaultRules: optionalNestedArray(module.defaultRules, r => [...r]),
|
||||
rules: nestedArray(module.rules, r => [...r])
|
||||
})),
|
||||
target: config.target,
|
||||
externals: config.externals,
|
||||
externalsType: config.externalsType,
|
||||
externalsPresets: cloneObject(config.externalsPresets),
|
||||
infrastructureLogging: cloneObject(config.infrastructureLogging),
|
||||
devtool: config.devtool,
|
||||
node: nestedConfig(config.node, node => node && {
|
||||
...node
|
||||
}),
|
||||
snapshot: nestedConfig(config.snapshot, snapshot => ({
|
||||
resolve: optionalNestedConfig(snapshot.resolve, resolve => ({
|
||||
timestamp: resolve.timestamp,
|
||||
hash: resolve.hash
|
||||
})),
|
||||
module: optionalNestedConfig(snapshot.module, module => ({
|
||||
timestamp: module.timestamp,
|
||||
hash: module.hash
|
||||
}))
|
||||
})),
|
||||
cache: optionalNestedConfig(config.cache, cache => cache),
|
||||
stats: nestedConfig(config.stats, stats => {
|
||||
if (stats === false) {
|
||||
return {
|
||||
preset: "none"
|
||||
};
|
||||
}
|
||||
if (stats === true) {
|
||||
return {
|
||||
preset: "normal"
|
||||
};
|
||||
}
|
||||
if (typeof stats === "string") {
|
||||
return {
|
||||
preset: stats
|
||||
};
|
||||
}
|
||||
return {
|
||||
...stats
|
||||
};
|
||||
}),
|
||||
optimization: nestedConfig(config.optimization, optimization => {
|
||||
return {
|
||||
...optimization,
|
||||
runtimeChunk: getNormalizedOptimizationRuntimeChunk(optimization.runtimeChunk),
|
||||
splitChunks: nestedConfig(optimization.splitChunks, splitChunks => splitChunks && {
|
||||
...splitChunks,
|
||||
cacheGroups: cloneObject(splitChunks.cacheGroups)
|
||||
})
|
||||
};
|
||||
}),
|
||||
plugins: nestedArray(config.plugins, p => [...p]),
|
||||
experiments: nestedConfig(config.experiments, experiments => ({
|
||||
...experiments,
|
||||
incrementalRebuild: optionalNestedConfig(experiments.incrementalRebuild, options => (options === true ? {} : options))
|
||||
})),
|
||||
watch: config.watch,
|
||||
watchOptions: cloneObject(config.watchOptions),
|
||||
devServer: config.devServer,
|
||||
profile: config.profile,
|
||||
builtins: nestedConfig(config.builtins, builtins => ({
|
||||
...builtins
|
||||
}))
|
||||
};
|
||||
};
|
||||
exports.getNormalizedRspackOptions = getNormalizedRspackOptions;
|
||||
const getNormalizedEntryStatic = (entry) => {
|
||||
if (typeof entry === "string") {
|
||||
return {
|
||||
main: {
|
||||
import: [entry]
|
||||
}
|
||||
};
|
||||
}
|
||||
if (Array.isArray(entry)) {
|
||||
return {
|
||||
main: {
|
||||
import: entry
|
||||
}
|
||||
};
|
||||
}
|
||||
const result = {};
|
||||
for (const key of Object.keys(entry)) {
|
||||
const value = entry[key];
|
||||
if (typeof value === "string") {
|
||||
result[key] = {
|
||||
import: [value]
|
||||
};
|
||||
}
|
||||
else if (Array.isArray(value)) {
|
||||
result[key] = {
|
||||
import: value
|
||||
};
|
||||
}
|
||||
else {
|
||||
result[key] = {
|
||||
import: Array.isArray(value.import) ? value.import : [value.import],
|
||||
runtime: value.runtime,
|
||||
publicPath: value.publicPath,
|
||||
baseUri: value.baseUri,
|
||||
chunkLoading: value.chunkLoading,
|
||||
asyncChunks: value.asyncChunks,
|
||||
filename: value.filename,
|
||||
library: value.library
|
||||
};
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
const getNormalizedOptimizationRuntimeChunk = (runtimeChunk) => {
|
||||
if (runtimeChunk === undefined)
|
||||
return undefined;
|
||||
if (runtimeChunk === false)
|
||||
return false;
|
||||
if (runtimeChunk === "single") {
|
||||
return {
|
||||
name: () => "runtime"
|
||||
};
|
||||
}
|
||||
if (runtimeChunk === true || runtimeChunk === "multiple") {
|
||||
return {
|
||||
name: (entrypoint) => `runtime~${entrypoint.name}`
|
||||
};
|
||||
}
|
||||
const { name } = runtimeChunk;
|
||||
const opts = {
|
||||
name: typeof name === "function" ? name : () => name
|
||||
};
|
||||
return opts;
|
||||
};
|
||||
const nestedConfig = (value, fn) => value === undefined ? fn({}) : fn(value);
|
||||
const optionalNestedConfig = (value, fn) => (value === undefined ? undefined : fn(value));
|
||||
const nestedArray = (value, fn) => Array.isArray(value) ? fn(value) : fn([]);
|
||||
const optionalNestedArray = (value, fn) => (Array.isArray(value) ? fn(value) : undefined);
|
||||
const cloneObject = (value) => ({ ...value });
|
||||
const keyedNestedConfig = (value, fn, customKeys) => {
|
||||
const result = value === undefined
|
||||
? {}
|
||||
: Object.keys(value).reduce((obj, key) => ((obj[key] = (customKeys && key in customKeys ? customKeys[key] : fn)(value[key])),
|
||||
obj), {});
|
||||
if (customKeys) {
|
||||
for (const key of Object.keys(customKeys)) {
|
||||
if (!(key in result)) {
|
||||
result[key] = customKeys[key]({});
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
|
@ -45,10 +45,10 @@
|
|||
"zod": "^3.21.4",
|
||||
"zod-validation-error": "1.2.0",
|
||||
"terminal-link": "^2.1.1",
|
||||
"@ice/pack-binding": "0.0.3",
|
||||
"@rspack/plugin-react-refresh": "0.4.0"
|
||||
"@ice/pack-binding": "0.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rspack/plugin-react-refresh": "0.4.0",
|
||||
"@rspack/dev-server": "0.4.0",
|
||||
"@rspack/core": "0.4.0",
|
||||
"@types/less": "^3.0.3",
|
||||
|
|
|
@ -230,7 +230,13 @@ const tasks = [
|
|||
// Copy the entire directory.
|
||||
// filter out js files and replace with compiled files.
|
||||
const filePaths = globbySync(['**/*'], { cwd: pkgPath, ignore: ['node_modules'] });
|
||||
const filesAddOverwrite = ['dist/config/adapter.js', 'dist/config/defaults.js', 'dist/config/zod.js', 'dist/util/bindingVersionCheck.js'];
|
||||
const filesAddOverwrite = [
|
||||
'dist/config/adapter.js',
|
||||
'dist/config/defaults.js',
|
||||
'dist/config/zod.js',
|
||||
'dist/config/normalization.js',
|
||||
'dist/util/bindingVersionCheck.js',
|
||||
];
|
||||
filePaths.forEach((filePath) => {
|
||||
const sourcePath = path.join(pkgPath, filePath);
|
||||
const targetFilePath = path.join(targetPath, filePath);
|
||||
|
@ -280,6 +286,30 @@ const tasks = [
|
|||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
pkgName: '@rspack/plugin-react-refresh',
|
||||
skipCompile: true,
|
||||
patch: () => {
|
||||
const pkgPath = path.join(__dirname, '../node_modules/@rspack/plugin-react-refresh');
|
||||
const filePaths = globbySync(['**/*'], { cwd: pkgPath, ignore: ['node_modules'] });
|
||||
filePaths.forEach((filePath) => {
|
||||
fs.ensureDirSync(path.join(__dirname, `../compiled/@rspack/plugin-react-refresh/${path.dirname(filePath)}`));
|
||||
const sourcePath = path.join(pkgPath, filePath);
|
||||
const targetPath = path.join(__dirname, `../compiled/@rspack/plugin-react-refresh/${filePath}`);
|
||||
if (path.extname(filePath) === '.js') {
|
||||
const fileContent = fs.readFileSync(sourcePath, 'utf8');
|
||||
fs.writeFileSync(targetPath,
|
||||
replaceDeps(fileContent, webpackDevServerDeps.concat([
|
||||
...commonDeps,
|
||||
'@rspack/core',
|
||||
])).replace(/@pmmmwh\/react-refresh-webpack-plugin\/lib\/runtime\/RefreshUtils/g, '@ice/bundles/compiled/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils'),
|
||||
);
|
||||
} else {
|
||||
fs.copyFileSync(sourcePath, targetPath);
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
export default tasks;
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
import RefreshPlugin from '@rspack/plugin-react-refresh';
|
||||
import RefreshPlugin from '../compiled/@rspack/plugin-react-refresh/dist/index.js';
|
||||
|
||||
export default RefreshPlugin;
|
||||
|
|
|
@ -6,7 +6,7 @@ import type { Configuration, rspack as Rspack } from '@rspack/core';
|
|||
import lodash from '@ice/bundles/compiled/lodash/index.js';
|
||||
import { coreJsPath } from '@ice/bundles';
|
||||
import RefreshPlugin from '@ice/bundles/esm/plugin-refresh.js';
|
||||
import getSplitChunks from './splitChunks.js';
|
||||
import getSplitChunks, { getFrameworkBundles } from './splitChunks.js';
|
||||
import getAssetsRule from './assetsRule.js';
|
||||
import getCssRules from './cssRules.js';
|
||||
|
||||
|
@ -25,6 +25,13 @@ type GetConfig = (
|
|||
options: GetRspackConfigOptions,
|
||||
) => Promise<Configuration>;
|
||||
|
||||
interface BuiltinFeatures {
|
||||
splitChunksStrategy?: {
|
||||
name: string;
|
||||
topLevelFrameworks: string[];
|
||||
};
|
||||
}
|
||||
|
||||
const require = createRequire(import.meta.url);
|
||||
|
||||
const { merge } = lodash;
|
||||
|
@ -108,6 +115,19 @@ const getConfig: GetConfig = async (options) => {
|
|||
},
|
||||
module: true,
|
||||
}, minimizerOptions);
|
||||
const builtinFeatures: BuiltinFeatures = {};
|
||||
let splitChunksStrategy = null;
|
||||
// Use builtin splitChunks strategy by default.
|
||||
if (splitChunks === true || splitChunks === 'chunks') {
|
||||
builtinFeatures.splitChunksStrategy = {
|
||||
name: 'chunks',
|
||||
topLevelFrameworks: getFrameworkBundles(rootDir),
|
||||
};
|
||||
} else {
|
||||
splitChunksStrategy = typeof splitChunks == 'object'
|
||||
? splitChunks
|
||||
: getSplitChunks(rootDir, splitChunks);
|
||||
}
|
||||
const config: Configuration = {
|
||||
entry: {
|
||||
main: [path.join(rootDir, runtimeTmpDir, 'entry.client.tsx')],
|
||||
|
@ -162,9 +182,7 @@ const getConfig: GetConfig = async (options) => {
|
|||
},
|
||||
optimization: {
|
||||
minimize: !!minify,
|
||||
splitChunks: typeof splitChunks == 'object'
|
||||
? splitChunks
|
||||
: getSplitChunks(rootDir, splitChunks),
|
||||
...(splitChunksStrategy ? { splitChunks: splitChunksStrategy } : {}),
|
||||
},
|
||||
// @ts-expect-error plugin instance defined by default in not compatible with rspack.
|
||||
plugins: [
|
||||
|
@ -212,7 +230,7 @@ const getConfig: GetConfig = async (options) => {
|
|||
...devServer,
|
||||
setupMiddlewares: middlewares,
|
||||
},
|
||||
features: {},
|
||||
features: builtinFeatures,
|
||||
};
|
||||
// Compatible with API configureWebpack.
|
||||
const ctx = {
|
||||
|
|
|
@ -13,7 +13,7 @@ function transformPathForRegex(str: string) {
|
|||
? str.replace(/\\$/, '').replace(/\\/g, '\\') : str;
|
||||
}
|
||||
|
||||
const getChunksStrategy = (rootDir: string) => {
|
||||
export const getFrameworkBundles = (rootDir: string) => {
|
||||
const frameworkPaths: string[] = [];
|
||||
const visitedFramework = new Set<string>();
|
||||
function addPackagePath(packageName: string, dir: string) {
|
||||
|
@ -40,7 +40,11 @@ const getChunksStrategy = (rootDir: string) => {
|
|||
FRAMEWORK_BUNDLES.forEach((packageName) => {
|
||||
addPackagePath(packageName, rootDir);
|
||||
});
|
||||
return frameworkPaths;
|
||||
};
|
||||
|
||||
export const getChunksStrategy = (rootDir: string) => {
|
||||
const frameworkPaths = getFrameworkBundles(rootDir);
|
||||
// Create test rule for framework.
|
||||
const frameworkTest = new RegExp(frameworkPaths.join('|'));
|
||||
return {
|
||||
|
@ -81,14 +85,14 @@ export const getVendorStrategy = (options: Configuration['splitChunks']) => {
|
|||
};
|
||||
};
|
||||
|
||||
const getSplitChunks = (rootDir: string, strategy: string | boolean) => {
|
||||
const getSplitChunks = (_: string, strategy: string | boolean) => {
|
||||
if (strategy === false) {
|
||||
return { minChunks: Infinity, cacheGroups: { default: false } };
|
||||
} else if (typeof strategy === 'string' && ['page-vendors', 'vendors'].includes(strategy)) {
|
||||
const splitChunksOptions = strategy === 'page-vendors' ? { chunks: 'all' } : {};
|
||||
return getVendorStrategy(splitChunksOptions);
|
||||
}
|
||||
return getChunksStrategy(rootDir);
|
||||
return {};
|
||||
};
|
||||
|
||||
export default getSplitChunks;
|
||||
|
|
|
@ -1279,9 +1279,6 @@ importers:
|
|||
'@ice/swc-plugin-remove-export':
|
||||
specifier: 0.2.0
|
||||
version: 0.2.0
|
||||
'@rspack/plugin-react-refresh':
|
||||
specifier: 0.4.0
|
||||
version: 0.4.0(react-refresh@0.14.0)(webpack-dev-server@4.15.0)(webpack@5.88.2)
|
||||
'@swc/core':
|
||||
specifier: 1.3.80
|
||||
version: 1.3.80
|
||||
|
@ -1370,6 +1367,9 @@ importers:
|
|||
'@rspack/dev-server':
|
||||
specifier: 0.4.0
|
||||
version: 0.4.0(@rspack/core@0.4.0)(@swc/core@1.3.80)(esbuild@0.17.16)(react-refresh@0.14.0)
|
||||
'@rspack/plugin-react-refresh':
|
||||
specifier: 0.4.0
|
||||
version: 0.4.0(react-refresh@0.14.0)(webpack-dev-server@4.15.0)(webpack@5.88.2)
|
||||
'@types/less':
|
||||
specifier: ^3.0.3
|
||||
version: 3.0.3
|
||||
|
@ -7662,6 +7662,7 @@ packages:
|
|||
source-map: 0.7.4
|
||||
webpack: 5.88.2(@swc/core@1.3.80)(esbuild@0.17.16)
|
||||
webpack-dev-server: 4.15.0(webpack@5.88.2)
|
||||
dev: true
|
||||
|
||||
/@polka/url@1.0.0-next.21:
|
||||
resolution: {integrity: sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==}
|
||||
|
@ -8170,7 +8171,7 @@ packages:
|
|||
- webpack-dev-server
|
||||
- webpack-hot-middleware
|
||||
- webpack-plugin-serve
|
||||
dev: false
|
||||
dev: true
|
||||
|
||||
/@sideway/address@4.1.4:
|
||||
resolution: {integrity: sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==}
|
||||
|
@ -11633,6 +11634,7 @@ packages:
|
|||
|
||||
/common-path-prefix@3.0.0:
|
||||
resolution: {integrity: sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==}
|
||||
dev: true
|
||||
|
||||
/commondir@1.0.1:
|
||||
resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==}
|
||||
|
|
Loading…
Reference in New Issue