跳到主要内容

从 ice.js 2.x 升级

前言

升级 ice.js 3.x 可以带来构建速度和页面性能的提升,并且带来更多移动端功能,比如开箱即用的 PHA、Weex 和小程序方案等。

升级指南

依赖修改

{
"devDependencies": {
- "ice.js": "^2.0.0",
+ "@ice/app": "^3.0.0",
+ "@ice/runtime": "^1.0.0",
}
}

对应插件能力:

  • @ali/build-plugin-ice-def -> @ali/ice-plugin-def
  • build-plugin-moment-locales -> @ice/plugin-moment-locales
  • build-plugin-fusion -> @ice/plugin-fusion (多主题能力暂不支持)
  • build-plugin-antd -> @ice/plugin-antd
  • build-plugin-css-assets-local -> @ice/plugin-css-assets-local
  • build-plugin-jsx-plus -> @ice/plugin-jsx-plus 文档
  • build-plugin-keep-alive 不再支持,有 ice.js 3.0 的 keep alive 方案替代

插件使用方式变更为函数调用:

ice.config.mts
import { defineConfig } from '@ice/app';
import jsxPlus from '@ice/plugin-jsx-plus';

export default defineConfig(() => ({
plugins: [
jsxPlus(),
],
}));

完成依赖升级后推荐重新安装依赖,即执行 npm update

工程配置文件升级

为了获取更好的类型提示,ice 新版本中推荐使用 ts 文件进行配置,即在项目目录下新增 ice.config.mts 文件,原 json 中的能力支持情况如下:

ice 2.xice 3.0备注
--port-
--host-
--config-
--disable-open-
plugins-
alias-
publicPath-
devPublicPath-
sourceMap-
externals-
hash-
outputDir-
proxy-
define-
ssr-
--disable-mock-
--https-
--analyzer-
dropLogLevel-
minify简化配置(true/false)
compileDependencies配合现有的 compileIncludes 能力
eslint-
tsChecker-
postcssOptions / postcssrc-
polyfill需要主动开启
remoteRuntime-
--disable-assets不常用通过环境变量控制日志输出详细程度
--disable-reload配置禁止 fastRefresh
terser内置方案
outputAssetsPath后续输出最佳目录实践
devServer不支持全量配置 devServer,按需开启 server 相关能力
browserslist统一走 browserlist 文件
vendor内置的分包实践,可以通过 splitChunks 关闭
libraryTarget / library / libraryExport-
cssLoaderOptions / lessLoaderOptions / sassLoaderOptions不支持 webpack loader 相关,内置配置
ignoreHtmlTemplate-
entry自定义场景走 client.entry.tsx
vite / vitePlugins-
swc-
store / auth / request / pwa / router通过定制的插件支持
disableRuntime-
babelPlugins / babelPresets / webpackPlugins / webpackLoaders不推荐直接配置

ice.js 3 新版本中不再支持 vite 模式,并且 webpack 相关的快捷配置也不再支持。我们将会将内置的逻辑做到最优。如果存在 webpack 定制需求,可以参考如下自定义方式定制:

ice.config.mts
import { defineConfig } from '@ice/app';
import { modifyLoader } from '@ice/webpack-modify';

export default defineConfig(() => ({
// Set your configs here.
// ...
webpack: (webpackConfig) => {
if (typeof webpackConfig.devServer?.client === 'object') {
// 修改 webpack 配置
webpackConfig.devServer.client.overlay = false;
}

// 修改内置的 webpack 规则,借助官方工具可以更便捷的修改
// 修改 css 样式规则下的 postcss-loader 配置项
return modifyLoader(webpackConfig, {
rule: '.css',
loader: 'postcss-loader',
options: (originOptions) => ({}),
});
}
}));

其他新版配置参考:链接 新版插件规范:链接

新版的 webpack 配置不再依赖 webpack-chain,如果有定制 webpack 的诉求可以直接通过 webpack-merge 的方式合并配置

常见配置迁移

新版框架对于大量配置进行了收敛,如果迁移时涉及到负责的定制场景,可以参考以下配置进行迁移

cssLoaderOptions

ice.config.mts
import { defineConfig } from '@ice/app';
import { modifyLoader } from '@ice/webpack-modify';

export default defineConfig(() => ({
// Set your configs here.
// ...
webpack: (webpackConfig) => {
return ['css', 'less', 'sass'].reduce((acc, cur) => {
return modifyLoader(acc, {
rule: `.${cur}`,
loader: 'css-loader',
options: (originOptions) => ({}),
});
}, webpackConfig);
},
}));

lessLoaderOptions

ice.config.mts
import { defineConfig } from '@ice/app';
import { modifyLoader } from '@ice/webpack-modify';

export default defineConfig(() => ({
// Set your configs here.
// ...
webpack: (webpackConfig) => {
return modifyLoader(webpackConfig, {
rule: '.less',
loader: 'less-loader',
options: (originOptions) => ({}),
});
},
}));

sassLoaderOptions

ice.config.mts
import { defineConfig } from '@ice/app';
import { modifyLoader } from '@ice/webpack-modify';

export default defineConfig(() => ({
// Set your configs here.
...
webpack: (webpackConfig) => {
return modifyLoader(webpackConfig, {
rule: '.sass',
loader: 'sass-loader',
options: (originOptions) => ({}),
});
}
}));

postcssOptions / postcssrc

ice.config.mts
import { defineConfig } from '@ice/app';
import { modifyLoader } from '@ice/webpack-modify';

export default defineConfig(() => ({
// Set your configs here.
// ...
webpack: (webpackConfig) => {
return ['css', 'less', 'sass'].reduce((acc, cur) => {
return modifyLoader(acc, {
rule: `.${cur}`,
loader: 'postcss-loader',
options: (originOptions) => ({}),
});
}, webpackConfig);
},
}));

如果希望使用 postcssrc 能力,将 options 配置成如上空对象即可

webpackPlugins

ice.config.mts
import { defineConfig } from '@ice/app';
import { removePlugin } from '@ice/webpack-modify';

export default defineConfig(() => ({
// Set your configs here.
// ...
webpack: (webpackConfig) => {
let modifiedConfig = webpackConfig;
// 添加插件
webpackConfig.plugins.push(new WebpackPlugin());
// webpack 插件修改,先删除插件在重新添加
modifiedConfig = removePlugin(webpackConfig, {
pluginName: 'AssetsManifestPlugin',
});
webpackConfig.plugins.push(new AssetsManifestPlugin());
}
}));

webpackLoaders

ice.config.mts
import { defineConfig } from '@ice/app';
import { addLoader, modifyLoader, removeLoader } from '@ice/webpack-modify';

export default defineConfig(() => ({
// Set your configs here.
//...
webpack: (webpackConfig) => {
let modifiedConfig = webpackConfig;
// 为 css 规则添加 loader
modifiedConfig = addLoader(modifiedConfig, {
rule: '.css',
before: 'css-loader',
useItem: {
loader: 'style-loader',
},
});
// 移除 loader
modifiedConfig = removeLoader(modifiedConfig, {
rule: '.css',
loader: 'css-loader',
});
// 修改 loader
modifiedConfig = modifyLoader(getWebpackConfig(), {
rule: '.css',
loader: 'css-loader',
options: () => ({ module: true }),
});
return modifiedConfig;
},
}));

babelPlugins / babelPresets

框架内置不再支持 babel 转换,一些常见语法转化逻辑已内置,如果存在定制 babel 插件的情况下,推荐以下方式转化

ice.config.mts
import { defineConfig } from '@ice/app';
import { transformSync } from '@babel/core';

export default defineConfig(() => ({
// Set your configs here.
// ...
transform: async (source, id) => {
// 过滤条件
if (id.match(/\.(j|t)s(x)?$/) && !id.includes('node_modules')) {
// 借助 babel 编译
const { code, map } = transformSync(source, {
plugins: ['transform-decorators-legacy'],
});
return { code, map };
}
},
}));

运行时修改

应用入口修改

- import { runApp } from 'ice';

const appConfing = {};

- runApp(appConfig);
+ export default appConfig;

为了获得良好类型提示,推荐写法为:

import { defineAppConfig } from 'ice';

export default defineAppConfig(() => ({
app: {
strict: false,
},
}));

原 appConfig 上大部分能力均通过不同的插件进行承载,目前应用入口能力,请参考文档

路由修改

为了提供更好的框架能力,新版 ice 默认提供的路由规则为约定式路由

原配置式路由推荐通过上述的规则重新组织目录结构,如果路由过于复杂,推荐如下方式进行迁移:

ice.config.mts
import { defineConfig } from '@ice/app';

export default defineConfig(() => ({
routes: {
// 忽略所有约定式规则
ignoreFiles: ['**'],
defineRoutes: (route) => {
// 指定根路由页面为 home/index.ts
route('/', 'home/index.tsx');
// 为 /product 路由添加 layout.tsx 作为 layout,并渲染 products.tsx 内容
route('/', 'layout.tsx', () => {
route('/product', 'products.tsx');
});
},
},
}));

进阶方案迁移

状态管理

使用状态管理方案需主动安装 @ice/plugin-store

$ npm i @ice/plugin-store -D

ice.config.mts 中添加插件:

ice.config.mts
import { defineConfig } from '@ice/app';
import store from '@ice/plugin-store';

export default defineConfig(() => ({
plugins: [
store({ resetPageState: true }),
],
}));

更多用法参考状态管理

数据请求

使用数据请求方案需主动安装 @ice/plugin-request

$ npm i @ice/plugin-request -D

ice.config.mts 中添加插件:

ice.config.mts
import { defineConfig } from '@ice/app';
import request from '@ice/plugin-request';

export default defineConfig(() => ({
plugins: [
request(),
],
}));

src/app.ts 中导出统一的请求配置:

src/app.ts
export const requestConfig = {
...
};

更多配置和用法参考网络请求

权限方案

使用权限方案需主动安装 @ice/plugin-auth

$ npm i @ice/plugin-auth -D

ice.config.mts 中添加插件:

ice.config.mts
import { defineConfig } from '@ice/app';
import auth from '@ice/plugin-auth';

export default defineConfig(() => ({
plugins: [
auth(),
],
}));

src/app.ts 中导出的权限配置:

src/app.ts
export const authConfig = {
...
};

更多配置和用法参考权限管理