Skip to main content

升级至V2

本文摘录了reSKRipt V2版本的所有破坏性变更,如果你正在使用1.x版本,可以参考本文进行升级。如果你在升级过程中遇到任何困难,欢迎在GitHub上提交Issue来咨询。

V2的主要更新为引入webpack-dev-sever 4.x版本,并以此为契机废弃部分不合理的接口,总体上调整有限。

自动检测

你可以先使用我们的迁移脚本对项目做一次快速地扫描:

# 保持在项目根目录下
npx @reskript/doctor migrate-v2

你会快速得到一份类似这样的报告:

⚠ @reskript/cli@1.x still installed, upgrade it to a fixed version of latest 2.x release
⚠ @reskript/cli-build@1.x still installed, upgrade it to a fixed version of latest 2.x release
⚠ @reskript/cli-dev@1.x still installed, upgrade it to a fixed version of latest 2.x release
⚠ @reskript/cli-lint@1.x still installed, upgrade it to a fixed version of latest 2.x release
⚠ @reskript/cli-play@1.x still installed, upgrade it to a fixed version of latest 2.x release
⚠ @reskript/config-lint@1.x still installed, upgrade it to a fixed version of latest 2.x release
⚠ can't find core-js installed, please install it
see: https://reskript.dev/docs/migration/v2#安装core-js
ℹ @reskript/* is installed with a version range, better to install a fixed version
see: https://reskript.dev/docs/migration/v2#推荐固定版本
⚠ play.injectResources in reskript.config.js is deprecated and replaced by defaultGlobalSetup
see: https://reskript.dev/docs/migration/v2#play相关
⚠ found files contains {ReactComponent} named import from svg, change to default import from .svg?react
src/components/Foo/Bar.tsx
src/components/Button/index.tsx
info

执行脚本的目录下必须有package.json,且不能是monorepo的根目录。

按照报告的说明进行修复后,如果依然有问题,以下是各变更的详细介绍。

每一位都要了解的

以下是V2版本中涉及到所有使用者的变化,无论你以什么样的形式使用reSKRipt,你都应该关心这些变更。

NodeJS版本

在V2中,NodeJS的最低版本要求升级为14.14.0,这是为了我们可以使用fs.rm函数更高效地进行目录、文件的清理。V1版本的NodeJS要求为14.13.1,所以你只要确保本地NodeJS版本符合要求,基本不需要关心由NodeJS带来的差异。

推荐固定版本

从V2版本开始,我们推荐你使用固定版本的方式安装@reskript/*包,如果你原本已经安装了相应的包,推荐你将版本范围前的^符号移除:

 "devDependencies": {
- "@reskript/cli": "^1.15.2",
- "@reskript/cli-babel": "^1.15.2",
- "@reskript/cli-build": "^1.15.2",
- "@reskript/cli-dev": "^1.15.2",
- "@reskript/cli-lint": "^1.15.2",
- "@reskript/cli-play": "^1.15.2",
- "@reskript/cli-test": "^1.15.2",
+ "@reskript/cli": "1.15.2",
+ "@reskript/cli-babel": "1.15.2",
+ "@reskript/cli-build": "1.15.2",
+ "@reskript/cli-dev": "1.15.2",
+ "@reskript/cli-lint": "1.15.2",
+ "@reskript/cli-play": "1.15.2",
+ "@reskript/cli-test": "1.15.2",
}

在移除^符号后,记得再重新运行一次安装命令,即npm installyarn installpnpm install以更新版本锁文件。

安装core-js

在V1版本中,reSKRipt会自带core-js并为你处理好polyfill的引入路径,让你不需要感知到它的存在。但随着时间的推移,我们发现这样做并不是一个合理的方案,它存在着一些不可忽视的问题:

  1. 由于需要正确处理core-js的路径,在构建过程中增加了大量额外的源码扫描和转义,使得构建的速度被拖慢不少。
  2. 在应用长期的维护过程中,因为core-js是一个间接的依赖,并不容易得到版本的更新。这致使应用的业务代码使用了新的特性时,由于core-js版本的落后无法补上相应的polyfill,让代码产生了问题。

出于这些考虑,在V2版本中,我们转为要求用户自行安装core-js。你只需要在本地简单地增加这一依赖即可:

# npm
npm install -D core-js
# yarn
yarn add -D core-js
# pnpm
pnpm add -D core-js

如果你没有安装core-js,在执行skr buildskr dev时会报错退出,提示信息也会引导你正确地安装依赖。

SVG使用方式变化

请参考导入SVG文件规则调整中的说明,V2版本中,如果你需要引入一个.svg文件并作为React组件来使用,你需要相应调整你的代码:

- import {ReactComponent as Icon} from './icon.svg';
+ import Icon from './icon.svg?react';

如果你在CSS中引用.svg文件,且使用了.svg?asset这样的形式,那么可以删除其中的?asset部分:

- background-url: url("./background.svg?asset");
+ background-url: url("./background.svg");

命令行变更

如果你使用skr buildskr devskr test等命令,以下这些变更是你需要关注的。

build

--src参数修改为--src-dir参数,功能保持不变。这常用于使用skr build构建demo等场景,你只需要参数名即可:

- skr build --src=demo
+ skr build --src-dir=demo

dev

--src参数修改为--src-dir参数。与skr build相同的调整,你只需要修改参数名:

- skr dev --src=demo
+ skr dev --src-dir=demo

--open参数已经改为--host参数。原有的--open参数取值localremote,用来指示skr dev调试时浏览器打开的地址是localhost还是本地的IP地址。


新的--host参数拥有更强大的功能,支持localhostloopbackip和任意自定义的域名。如果你的应用需要与域名强绑定,并且你通过修改hosts把特定的域名解析到了127.0.0.1,那么可以通过--host=my-app.dev这样的形式进行调试。

如果你原先使用着--open参数,可以根据你的取值进行相应的修改:

- skr dev --open=local
+ skr dev --host=localhost
- skr dev --open=remote
+ skr dev --host=ip

babel

--out参数修改为--out-dir参数。为了所有的命令有更一致地参数命名,与--src-dir相同,我们使用--out-dir来指定skr babel的输出目录。对于原先使用这一参数的情况,也可以通过简单地修改名称来升级:

- skr babel --out=dist
+ skr babel --out-dir-dist

test

skr test有比较大的调整。在V2的skr test中,我们支持了透传参数给jest,因此原有的除--cwd--target以外的参数都已经废弃了。新版透传给jest的参数需要在命令行中跟随在一个--分隔符之后。

一般来说,你可以简单地在命令中增加--分隔来实现升级:

- skr test --target=react --changedSince=HEAD --maxWorkers=4 src/utils
+ skr test --target=react src/utils -- --changedSince=HEAD --maxWorkers=4

在调整过程中,你需要将原有测试的路径参数放到--前面,其它除--cwd--target外的参数放到--的后面。

需要额外注意的是,原有的--collect-coverage-from参数与jest的参数不同,它需要被修改为--collectCoverageFrom

- skr test --target=react --collect-coverage-from=src/utils
+ skr test --target=react -- --collectCoverageFrom=src/utils

另外,如果你是使用npm run test去执行命令,并依旧想在命令行中传递额外参数给jest的话,你需要2个--分隔符:

- npm run test -- --changedSince=HEAD
+ npm run test -- -- --changedSince=HEAD

配置文件变更

如果你除了使用命令行外,在项目中还有reskript.config.js用于配置,那么你可能需要关心不少的配置变更。当然大部分变更都是简单的调整,我们有信心你可以在很短的时间内调整完毕。

对于reskript.config.js,我们在执行命令时有严格的结构校验,因此你不需要担心遗漏了什么修改使得应用出现错误。

build相关

build.defaultImportOptimization已经移除。如果你未曾见过这一个配置,那么你的应用不会有任何行为上的变化。

defaultImportOptimization配置用于控制是否针对antdlodash两个库的import语句进行优化。在新版本中,你可以使用build.uses参数控制更多的第三方库的优化,这个配置默认依然启用了对antdlodash的优化。

如果你原先禁用了这个配置,那么在V2版本中,你需要将uses设置为空数组,以关闭默认优化逻辑:

 exports.build = {
- defaultImportOptimization: false,
+ uses: [],
};

具体对build.uses的使用,可以参考构建配置 - 特殊第三方库的优化来了解。

入口配置相关

如果你有使用形如entries/index.config.js自定义入口配置功能,且在*.config.js中导出任意的属性以供自定义的模板中使用的话,这一方法已经被废弃了。在V2版本中,你需要将自定义的属性收集到exports.html对象中:

- exports.appVersion = '1.2.3';
- exports.copyrightYear = 2021;
+ exports.html = {
+ appVersion: '1.2.3',
+ copyrightYear: 2021,
+ };

除此之外,我们也支持在*.config.js中导出exports.entry配置入口的构建逻辑,具体可以参阅多应用入口 - 自定义入口配置了解。

devServer相关

由于V2版本最大的更新在于webpack-dev-server升级到了4.x版本,reskript.config.js中的exports.devServer也产生了相应的变化。

首先devServer.hot的值从原有的'simple' | 'all' | 'none'改为了单纯的boolean类型,我们发现并没有场景只需要simple模式的热更新,同时由react-refresh驱动的组件热更新也已经非常成熟,因此简化了热更新的配置。

 exports.devServer = {
- hot: 'all',
+ hot: true,
};
// 如果需要关闭热更新
exports.devServer = {
- hot: 'none',
+ hot: false,
};

devServer.finalize强依赖于webpack-dev-server的配置格式,因此如果你有使用这个配置,也需要进行相应的修改。具体的修改与官方的更新对应,你可以通过官方升级指南来进行相应修改。

一般来说,你通过devServer.finalize调整的常用配置不受版本更新的影响,但有2个常见的案例可供参考。

如果你原本通过watchOptions.ignored配置调整本地监听的文件变更,可以做出相应的修改:

 export.devServer = {
finalize: devServerConfig => {
- devServerConfig.watchOptions.ignored = undefined;
+ devServerConfig.static.watch.ignored = undefined;
return devServerConfig;
},
};

如果你使用beforeafter来挂载自己的路径,也需要根据官方的升级进行调整,此处以before为例:

 export.devServer = {
finalize: devServerConfig => {
- const {before} = devServerConfig;
+ const {onBeforeSetupMiddleware} = devServerConfig;
- devServerConfig.before = (app, server, compiler) => {
+ devServerConfig.onBeforeSetupMiddleware = devServer => {
- before?.(app, server, compiler);
+ onBeforeSetupMiddleware?.(devServer);
- app.get(
+ devServer.app.get(
'/version',
(req, res) => {
res.status(200).type('html').end(`${packageInfo.name}@${packageInfo.version}`);
},
),
};
return devServerConfig;
},
};

play相关

play.wrapperplay.injectResources配置现在都已经废弃了,取而代之的是全局的初始化模块play.defaultGlobalSetup配置。

通过play.defaultGlobalSetup你可以指定一个模块作为所有skr play命令的全局初始化,你可以参考单组件调试配置 - 全局配置来了解它的作用。

原有的play.wrapper可以使用全局配置中的export function Wrapper来代替:

- exports.play = {
- wrapper: '<div style={{padding: 20}}>{children}</div>,
- };
// 在初始化模块中
+ export function Wrapper({children}) {
+ return (
+ <div style={{padding: 20}}>
+ {children}
+ </div>
+ );
+ }

injectResources则可以转换为全局配置中单纯的import语句:

- exports.play = {
- injectResources: [
- path.join(__diranme, 'src', 'styles', 'app.global.css'),
- ],
- };
// 在初始化模块中
+ import '@/styles/app.global.css';

API和细节变更

如果你除了使用命令行和配置文件外,还会主动import引用@reskript/*包并调用它们的内部API,那么以下是相关变更的摘要:

  • @reskript/config-babel包的相关函数中的hot配置从'simple' | 'all' | 'none'修改为boolean类型。
  • @reskript/config-babel包的defaultImportOptimization参数已经废弃,改用uses参数。
  • @reskript/settings中导出的函数均修改为异步接口,特别是readProjectSettings是你需要重点关心的。
  • @reskript/core中的辅助函数均修改为异步接口。
  • @reskript/config-webpack中的createWebpackConfig修改为异步函数,且参数有较大的调整。
  • @reskript/config-webpack导出的loaders字典中的svgurl属性已经移除,没有替代品,V2版本使用Webpack Asset Modules处理静态文件。
  • @reskript/config-dev-server中的createWebpackDevServerConfigcreateWebpackDevServerPartial修改为异步函数,且参数有较大的调整。
  • 所有涉及到BuildContext这一类型(包括RuntimeBuildContextBuildEntry)的逻辑,其中cache属性由boolean类型变更为'persist' | 'transient' | 'off',原cache: true对应cache: 'persist'
  • est-compat功能已经被移除,大概率你是不知道这个东西的。
  • skr build默认不再检查路径大小写是否正确,如果需要该功能请使用skr build --strict打开严格模式。严格模式同时会带来更多的校验和检查。