Compare commits

...

9 Commits

Author SHA1 Message Date
ClarkXia 0fdffb3adf
Merge e5edb831a4 into bb60ab5a04 2025-07-11 11:05:11 +08:00
ClarkXia bb60ab5a04
feat: support option rootId to empty root (#7031)
CI / build (16.x, ubuntu-latest) (push) Has been cancelled Details
CI / build (16.x, windows-latest) (push) Has been cancelled Details
CI / build (18.x, ubuntu-latest) (push) Has been cancelled Details
CI / build (18.x, windows-latest) (push) Has been cancelled Details
Coverage / coverage (16.x) (push) Has been cancelled Details
Release / Release (16) (push) Has been cancelled Details
2025-07-09 10:59:28 +08:00
ClarkXia 412faf03d1
Feat: support externals field in assets-manifest (#7116) (#7117)
* feat: support externals field in assets-manifest (#7116)

* chore: version

* chore: update version
2025-07-09 10:59:06 +08:00
ClarkXia e5edb831a4 chore: changelog 2024-07-31 10:32:49 +08:00
ClarkXia d775cdbc29 Merge branch 'release/next' into fix/optimize-route-config 2024-07-30 19:08:55 +08:00
ClarkXia 4b465456d6 fix: ts type 2024-07-12 10:02:53 +08:00
ClarkXia 8aa692864f feat: support remove asset mainfest in entry file 2024-07-11 20:25:36 +08:00
ClarkXia a8788f95a9 fix: optimize code 2024-07-10 18:03:36 +08:00
ClarkXia a305920aca fix: optimize the route code generated by framework 2024-07-10 17:37:15 +08:00
22 changed files with 127 additions and 52 deletions

View File

@ -0,0 +1,5 @@
---
'@ice/app': patch
---
fix: optimize the route code generate by framework

View File

@ -0,0 +1,7 @@
---
'@ice/webpack-config': patch
'@ice/rspack-config': patch
'@ice/shared-config': patch
---
fix: support remove the manifest info from bundle

View File

@ -28,7 +28,9 @@ const getDefaultTaskConfig = ({ rootDir, command }): Config => {
'universal-env': envReplacement, 'universal-env': envReplacement,
'@uni/env': envReplacement, '@uni/env': envReplacement,
}, },
assetsManifest: true, assetsManifest: {
inject: true,
},
fastRefresh: command === 'start', fastRefresh: command === 'start',
logging: process.env.WEBPACK_LOGGING || defaultLogging, logging: process.env.WEBPACK_LOGGING || defaultLogging,
minify: command === 'build', minify: command === 'build',

View File

@ -89,39 +89,10 @@ export function getRoutesDefinition(options: GetDefinationOptions) {
routeImports.push(`import * as ${routeSpecifier} from '${formatPath(componentPath)}';`); routeImports.push(`import * as ${routeSpecifier} from '${formatPath(componentPath)}';`);
loadStatement = routeSpecifier; loadStatement = routeSpecifier;
} }
const component = `Component: () => WrapRouteComponent({ // Keep the string in a single line for the code style.
routeId: '${id}', const lazyStatment = `lazyLoadComponent(${lazy ? 'componentModule' : loadStatement}, { routeId: '${id}', ${layout ? `layout: ${layout}, ` : ''}renderMode, requestContext })`;
isLayout: ${layout}, const routeProperties: string[] = [`...getRouteProps({ path: '${formatPath(routePath || '')}', componentName: '${componentName}', ${index ? `index: ${index}, ` : ''}id: '${id}',${layout ? `layout: ${layout}, ` : ''}exports: ${JSON.stringify(exports)} }),`];
routeExports: ${lazy ? 'componentModule' : loadStatement}, routeProperties.push(`async lazy() {${lazy ? `const componentModule = await ${loadStatement}` : ''}; return ${lazyStatment};},`);
})`;
const loader = `loader: createRouteLoader({
routeId: '${id}',
requestContext,
renderMode,
module: ${lazy ? 'componentModule' : loadStatement},
})`;
const routeProperties: string[] = [
`path: '${formatPath(routePath || '')}',`,
`async lazy() {
${lazy ? `const componentModule = await ${loadStatement}` : ''};
return {
${lazy ? '...componentModule' : `...${loadStatement}`},
${component},
${loader},
};
},`,
// Empty errorElement to avoid default ui provided by react-router.
'errorElement: <RouteErrorComponent />,',
`componentName: '${componentName}',`,
`index: ${index},`,
`id: '${id}',`,
'exact: true,',
`exports: ${JSON.stringify(exports)},`,
].filter(Boolean);
if (layout) {
routeProperties.push('layout: true,');
}
if (children) { if (children) {
const res = getRoutesDefinition({ const res = getRoutesDefinition({
manifest: children, manifest: children,

View File

@ -1,5 +1,53 @@
import * as React from 'react';
import { createRouteLoader, WrapRouteComponent, RouteErrorComponent } from '@ice/runtime'; import { createRouteLoader, WrapRouteComponent, RouteErrorComponent } from '@ice/runtime';
import type { CreateRoutes } from '@ice/runtime'; import type { CreateRoutes } from '@ice/runtime';
import type { ComponentModule, RenderMode, RequestContext } from '@ice/runtime/types';
interface RouteOptions {
routeId: string;
layout?: boolean;
renderMode: RenderMode;
requestContext?: RequestContext;
}
function lazyLoadComponent(componentModule: ComponentModule, options: RouteOptions) {
const { routeId, layout, renderMode, requestContext } = options;
return {
...componentModule,
Component: () => WrapRouteComponent({
routeId: routeId,
isLayout: Boolean(layout),
routeExports: componentModule,
}),
loader: createRouteLoader({
routeId: options.routeId,
requestContext,
renderMode,
module: componentModule,
}),
};
}
interface GetRoutePropsOptions {
path: string;
componentName: string;
index?: any;
id: string;
exports: string[];
layout?: boolean;
}
function getRouteProps(options: GetRoutePropsOptions) {
const { path, componentName, index, id, exports, layout } = options;
return {
path,
componentName,
errorElement: <RouteErrorComponent />,
index,
id,
exports,
layout: Boolean(layout),
exact: true,
};
}
<%- routeImports.length ? routeImports.join('\n') + '\n\n' : ''; -%> <%- routeImports.length ? routeImports.join('\n') + '\n\n' : ''; -%>
const createRoutes: CreateRoutes = ({ const createRoutes: CreateRoutes = ({
requestContext, requestContext,

View File

@ -1,5 +1,11 @@
# @ice/plugin-externals # @ice/plugin-externals
## 1.0.1
### Patch Changes
- 4569200ca: fix: support externals field in assets-manifest
## 1.0.0 ## 1.0.0
- Initial release - Initial release

View File

@ -1,6 +1,6 @@
{ {
"name": "@ice/plugin-externals", "name": "@ice/plugin-externals",
"version": "1.0.0", "version": "1.0.1",
"description": "plugin to make externals much easier in ice.js", "description": "plugin to make externals much easier in ice.js",
"files": [ "files": [
"esm", "esm",

View File

@ -26,7 +26,9 @@ export default class InjectExternalScriptsWebpackPlugin {
if (assetsManifest) { if (assetsManifest) {
const json = JSON.parse(assetsManifest.source().toString()); const json = JSON.parse(assetsManifest.source().toString());
delete compilation.assets[ASSET_MANIFEST_JSON_NAME]; delete compilation.assets[ASSET_MANIFEST_JSON_NAME];
json.entries.main.unshift(...this.options.externals); // Ensure externals array exists and add new externals at the beginning.
json.externals ||= [];
json.externals.unshift(...this.options.externals);
compilation.emitAsset( compilation.emitAsset(
ASSET_MANIFEST_JSON_NAME, ASSET_MANIFEST_JSON_NAME,
new webpack.sources.RawSource(JSON.stringify(json)), new webpack.sources.RawSource(JSON.stringify(json)),

View File

@ -56,7 +56,7 @@
"webpack-dev-server": "4.15.0" "webpack-dev-server": "4.15.0"
}, },
"peerDependencies": { "peerDependencies": {
"@ice/app": "^3.6.4", "@ice/app": "^3.6.3",
"@ice/runtime": "^1.5.4" "@ice/runtime": "^1.5.4"
}, },
"publishConfig": { "publishConfig": {

View File

@ -50,7 +50,7 @@
"sax": "^1.2.4" "sax": "^1.2.4"
}, },
"devDependencies": { "devDependencies": {
"@ice/app": "^3.6.4", "@ice/app": "^3.6.3",
"@ice/runtime": "^1.5.4", "@ice/runtime": "^1.5.4",
"webpack": "^5.88.0" "webpack": "^5.88.0"
}, },

View File

@ -1,5 +1,9 @@
# @ice/plugin-stream-error # @ice/plugin-stream-error
## 1.0.3
- feat: empty root element when stream error
## 1.0.0 ## 1.0.0
### Major Changes ### Major Changes

View File

@ -1,6 +1,6 @@
{ {
"name": "@ice/plugin-stream-error", "name": "@ice/plugin-stream-error",
"version": "1.0.2", "version": "1.0.3",
"description": "", "description": "",
"license": "MIT", "license": "MIT",
"type": "module", "type": "module",

View File

@ -2,13 +2,16 @@ import type { Plugin } from '@ice/app/types';
interface PluginOptions { interface PluginOptions {
activeInDev?: boolean; activeInDev?: boolean;
rootId?: string;
} }
const PLUGIN_NAME = '@ice/plugin-stream-error'; const PLUGIN_NAME = '@ice/plugin-stream-error';
const plugin: Plugin<PluginOptions> = (options = {}) => ({ const plugin: Plugin<PluginOptions> = (options = {
rootId: 'root',
}) => ({
name: PLUGIN_NAME, name: PLUGIN_NAME,
setup: ({ generator, context }) => { setup: ({ generator, context }) => {
const { activeInDev } = options; const { activeInDev, rootId } = options;
const { userConfig } = context; const { userConfig } = context;
if (userConfig.ssr) { if (userConfig.ssr) {
generator.addEntryCode((originalCode) => { generator.addEntryCode((originalCode) => {
@ -18,6 +21,11 @@ if (import.meta.renderer === 'client') {
// _$ServerTimePoints will returned at the end of last stream, // _$ServerTimePoints will returned at the end of last stream,
// if the value is undefined, try to re-render app with CSR. // if the value is undefined, try to re-render app with CSR.
if (${activeInDev ? '' : 'process.env.NODE_ENV === \'production\' && '}!window._$ServerTimePoints && window.__ICE_APP_CONTEXT__.renderMode === 'SSR') { if (${activeInDev ? '' : 'process.env.NODE_ENV === \'production\' && '}!window._$ServerTimePoints && window.__ICE_APP_CONTEXT__.renderMode === 'SSR') {
const root = document.getElementById('${rootId}');
if (root) {
root.innerHTML = '';
}
window.__ICE_APP_CONTEXT__.renderMode = 'CSR';
render({ hydrate: false }); render({ hydrate: false });
} }
}); });

View File

@ -149,7 +149,7 @@ const getConfig: GetConfig = async (options) => {
module: true, module: true,
}, minimizerOptions); }, minimizerOptions);
const builtinFeatures: BuiltinFeatures = { const builtinFeatures: BuiltinFeatures = {
assetsManifest, assetsManifest: Boolean(assetsManifest),
}; };
let splitChunksStrategy = null; let splitChunksStrategy = null;
// Use builtin splitChunks strategy by default. // Use builtin splitChunks strategy by default.

View File

@ -1,5 +1,11 @@
# @ice/runtime # @ice/runtime
## 1.5.5
### Patch Changes
- 4569200ca: fix: support externals field in assets-manifest
## 1.5.4 ## 1.5.4
### Patch Changes ### Patch Changes

View File

@ -1,6 +1,6 @@
{ {
"name": "@ice/runtime", "name": "@ice/runtime",
"version": "1.5.4", "version": "1.5.5",
"description": "Runtime module for ice.js", "description": "Runtime module for ice.js",
"type": "module", "type": "module",
"types": "./esm/index.d.ts", "types": "./esm/index.d.ts",

View File

@ -129,6 +129,9 @@ export const Scripts: ScriptsType = (props: ScriptsProps) => {
return ( return (
<> <>
<Data ScriptElement={ScriptElement} /> <Data ScriptElement={ScriptElement} />
{assetsManifest.externals?.map(external => (
<ScriptElement key={external} src={external} {...rest} data-external-script />
))}
{ {
routeScripts.map(routeScriptProps => { routeScripts.map(routeScriptProps => {
return <ScriptElement key={routeScriptProps.src} {...rest} {...routeScriptProps} data-route-script />; return <ScriptElement key={routeScriptProps.src} {...rest} {...routeScriptProps} data-route-script />;

View File

@ -205,6 +205,7 @@ export interface RouteModules {
} }
export interface AssetsManifest { export interface AssetsManifest {
externals?: string[];
dataLoader?: string; dataLoader?: string;
publicPath: string; publicPath: string;
entries: { entries: {

View File

@ -179,7 +179,7 @@ export interface Config {
performance?: Performance; performance?: Performance;
assetsManifest?: boolean; assetsManifest?: boolean | { inject: boolean };
concatenateModules?: boolean; concatenateModules?: boolean;

View File

@ -298,6 +298,7 @@ export function getWebpackConfig(options: GetWebpackConfigOptions): Configuratio
assetsManifest && new AssetsManifestPlugin({ assetsManifest && new AssetsManifestPlugin({
fileName: 'assets-manifest.json', fileName: 'assets-manifest.json',
outputDir: path.join(rootDir, runtimeTmpDir), outputDir: path.join(rootDir, runtimeTmpDir),
inject: typeof assetsManifest === 'boolean' ? false : assetsManifest?.inject,
}), }),
analyzer && new BundleAnalyzerPlugin(), analyzer && new BundleAnalyzerPlugin(),
tsCheckerOptions && new ForkTsCheckerPlugin(tsCheckerOptions), tsCheckerOptions && new ForkTsCheckerPlugin(tsCheckerOptions),

View File

@ -21,13 +21,22 @@ function filterAssets(assets: Assets): string[] {
); );
} }
interface PluginOptions {
fileName?: string;
outputDir?: string;
// Inject assets manifest to entry file.
inject?: boolean;
}
export default class AssetsManifestPlugin { export default class AssetsManifestPlugin {
private fileName: string; private fileName: string;
private outputDir: string; private outputDir: string;
private inject: boolean;
public constructor(options) { public constructor(options: PluginOptions) {
this.fileName = options.fileName || 'assets-manifest.json'; this.fileName = options.fileName || 'assets-manifest.json';
this.outputDir = options.outputDir || './'; this.outputDir = options.outputDir || './';
this.inject = options.inject;
} }
public createAssets(compilation: Compilation) { public createAssets(compilation: Compilation) {
@ -77,12 +86,14 @@ export default class AssetsManifestPlugin {
// Emit asset manifest for server compile. // Emit asset manifest for server compile.
compilation.emitAsset(this.fileName, new webpack.sources.RawSource(output)); compilation.emitAsset(this.fileName, new webpack.sources.RawSource(output));
// Inject assets manifest to entry file. // Inject assets manifest to entry file.
entryFiles.forEach((entryFile) => { if (this.inject) {
compilation.assets[entryFile] = new webpack.sources.ConcatSource( entryFiles.forEach((entryFile) => {
new webpack.sources.RawSource(String(`window.__ICE_ASSETS_MANIFEST__=${output};\n`)), compilation.assets[entryFile] = new webpack.sources.ConcatSource(
compilation.assets[entryFile], new webpack.sources.RawSource(String(`window.__ICE_ASSETS_MANIFEST__=${output};\n`)),
); compilation.assets[entryFile],
}); );
});
}
} }
public apply(compiler: Compiler) { public apply(compiler: Compiler) {

View File

@ -2157,7 +2157,7 @@ importers:
version: 1.2.4 version: 1.2.4
devDependencies: devDependencies:
'@ice/app': '@ice/app':
specifier: ^3.6.4 specifier: ^3.6.3
version: link:../ice version: link:../ice
'@ice/runtime': '@ice/runtime':
specifier: ^1.5.4 specifier: ^1.5.4