vite构建项⽬并⽀持微前端
⽬录
基础配置
⽀持微前端构建
其他说明
1. ⽼旧浏览器的⽀持
2. 关于 TypeScript 的说明
3. 对接 CDN
4. 构建出错
4.1 不到包
4.2 请求超时
4.3 导⼊模块出错
⼩结
得益于,vite 在诞⽣之初就备受关注,且⼀直保持着活跃的开发迭代。截⾄⽬前,vite 已经迭代到了 2.7.10 版本,各⽅⾯也基本具备了在⽣产使⽤的条件。这段时间,我在项⽬中尝试了使⽤ vite 进⾏打包构建,本⽂就是这次构建的过程记录。
基础配置
⾸先使⽤⽣成项⽬。
yarn create vite vite-demo --template react-ts
上⾯这⾏命令使⽤react-ts模板创建了⼀个叫vite-demo的项⽬。由于我在的团队⽇常使⽤ react 和 typescript 开发居多,因此选择了react-ts这个模板,vite 官⽅⽀持的模板还有很多,可以在中查看。
项⽬初始化完成以后,⽬录结构如下:
.
|____index.html
|____.gitignore
|____package.json
|____tsconfig.json
|____fig.ts
|____src
| |____App.tsx
| |____main.tsx
| |____App.css
| |____index.css
| |____vite-env.d.ts
| |____logo.svg
| |____favicon.svg
其中 fig.ts 内容如下:
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
// vitejs.dev/config/
export default defineConfig({
plugins: [react()]
})
可以看出,vite 官⽅已经做了⽐较完善的封装,相较于之前版本,开发体验提升了很多。
按照指⽰安装完依赖,启动应⽤以后,速度确实很快。现在我们来做⼀些基本改造。
我通常使⽤ less 来写样式,vite 已经做了很好的⽀持,在安装完依赖以后,只需要直接在代码中引⽤xxx.less即可。对于⼀个久经考验的开发者来说,样式还是要引⼊作⽤域的,通常使⽤ css modules。
安装 less 预处理器,
yarn add --dev less
然后修改fig.ts⽂件,添加 css modules 配置:
export default defineConfig({
...
css: {
modules: {
localsConvention: 'camelCaseOnly', // 我们使⽤驼峰形式
},
},
...
})
添加完配置以后,只要将原来的xxx.less改成dule.less即可,这点与 create-react-app 是⼀样的。
这⾥推荐⼀个 vscode 插件可以实现编码时样式类名的智能提⽰,同时点击样式类名可以跳转到样式定义的地⽅,⾮常好⽤。如果在编写样式时使⽤的是中划线形式的命名⽅式,⽐如.xxx-container,那么需要额外配置这个 vscode 插件,如下
{
"cssModules.camelCase": true
}
这样可以实现编写样式时使⽤中划线形式,在代码中使⽤的还是驼峰式的。
由于我开发的是⼀个中后台项⽬,使⽤了 antd 和 lodash,⼤家都知道,这两个是按需加载⼤户,以前我们使⽤来处理,vite ⽣态⾥也有很多类似的⽅案。我选⽤了这个插件,修改fig.ts如下:
import vitePluginImp from 'vite-plugin-imp';
export default defineConfig({
...
plugins: [
...
vitePluginImp({
libList: [
{
libName: 'lodash',
libDirectory: '',
camel2DashComponentName: false,
},
{
libName: 'antd',
style(name) {
// use less
return `antd/es/${name}/style/index.js`;
},
},
],
}),
],
css: {
...
preprocessorOptions: {
less: {
javascriptEnabled: true,
},
},
},
});
antd 已经默认⽀持了 Tree Shaking,上⾯的配置最终只会处理样式的按需加载。lodash 不⽀持 Tree Shaking,我们也可以使⽤ ESM 版本,这样就可以不使⽤ vite-plugin-imp 了,配置如下:
export default defineConfig({
resolve: {
alias: [{
find: /^lodash$/,
replacement: 'lodash-es',
}],
},
});
通常,我们在开发前端项⽬时,需要⼀些代理来调⽤后端 API 接⼝,vite 配置如下:
export default defineConfig({
...
server: {
proxy: {
'/api_path/': {
target: 'xxx.server.domain/',
changeOrigin: true,
},
},
},
});
代理底层都是基于实现,这⾥不做过多说明了。
现在可以愉快的开发代码了。
⽀持微前端构建
因为我们的中后台应⽤是使⽤微前端(qiankun)来管理的,上⾯的配置,打包完成后不能被 qiankun 识别,主要原因可以看看,我们需要做⼀些额外处理。
我们知道,使⽤ webpack 构建微前端是,需要添加如下三个配置项:
{
output: {
libraryTarget: 'umd',
library: `${APP_NAME}-[name]`,
jsonpFunction: `webpackJsonp_${APP_NAME}`,
}
}
在 vite 中,可以直接通过设置llupOptions.format为umd来设置 UMD 规范,但是实际构建结果却不能被 qiankun 识别,猜想是可能跟 vite 使⽤ html entry 有关系。
换⼀个思路,我们把当前整个应⽤当做⼀个 library 来构建,输出为 UMD 规范,然后⼿动写⼊⼀个 html ⽂件,加载这个输出的 JS。
修改配置如下:
export default defineConfig({
...
build: {
lib: {
name,
entry: solve(__dirname, 'src/index.tsx'),
formats: ['umd'],
},
},
...
})
配置完成之后,执⾏yarn build提⽰如下错误:
UMD and IIFE output formats are not supported for code-splitting builds.
因为我们的应⽤中有路由,使⽤了按需加载。我们将 rollup 的inlineDynamicImports配置打开:
export default defineConfig({
...
build: {
rollupOptions: {
output: {
inlineDynamicImports: true,
},
},
},
...
})
这样,构建完成之后,dist ⽬录下有两个⽂件style.css和xxx.umd.js。
现在我们要⽣成index.html了。
因为 vite 在开发态直接使⽤ ES Modules,是不打包的,因此⽣成开发态的index.html和⽣产的index.html是不同的。
我们修改项⽬根⽬录下的index.html为:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/src/favicon.svg" rel="external nofollow" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title>
<!-- style placeholder -->
</head>
<body>
<div id="root"></div>
<!-- script placeholder -->
</body>
</html>
注意当中的两⾏注释,我们会在开发态和⽣产构建做不同的处理。
vite 插件 API 中有⼀个可以定制开发态的 html 内容,因此,我们开发态的配置如下:// vitejs.dev/config/
export default defineConfig({
...
plugins: [
...
{
name: 'dev html',
apply: 'serve',
transformIndexHtml(indexHtml: string) {
return indexHtml
.replace('<!-- style placeholder -->', '')
.replace('<!-- script placeholder -->', '<script type="module" src="/src/index.tsx"></script>');
},
},
...
],
});
⽣产构建需要借助于这个插件来实现定制 html 内容。
import html from '@rollup/plugin-html';
import fs from 'fs';
const entryHtml = fs.readFileSync('./index.html', { encoding: 'utf-8' });
export default defineConfig({
...
plugins: [
...
{
name: 'build html',
apply: 'build',
...html({
template: () => {
return entryHtml
.
replace(
'<!-- style placeholder -->',
'<link rel="stylesheet" type="text/css" href="style.css" rel="external nofollow" />',
)
.replace(
'<!-- script placeholder -->',
`<script type="text/javascript" src="${name}.umd.js"></script>`,
);
},
}),
},
.
..
],
});svg的类型有几种
通过上⾯的配置,再次构建,qiankun 可以加载这个⼦应⽤了。
其他说明
1. ⽼旧浏览器的⽀持
由于我这次的项⽬是中后台项⽬,对⽼旧浏览器的⽀持诉求不强烈,就没有在项⽬中做处理。其实 vite 官⽅也是给了解决⽅案的,就是这个插件。
原理也⾮常简单,就是通过<script nomodule>来实现在不⽀持 ES Modules 的浏览器执⾏相关脚本,同时使⽤来加载模块。
2. 关于 TypeScript 的说明
脚⼿架初始化完成以后就可以⽤ TypeScript 开发,这⾥格外说明⼀点,就是需要开启编译器选项isolate
dModules:true,因为 vite 使⽤ esbuild 处理 ts ⽂件,只将 ts转换成 js ⽽不做类型检查(依赖编辑器处理类型检查,⽐如 vscode)。因此,当遇到⼀些纯类型的导⼊导出时,会出错,需要开启isolatedModules:true来避免这个问题。如果因为⼀些原因⽆法开启这个选项,则可以使⽤这个包来处理,这个包的 README ⾥也说明了为什么会有这样的问题。
3. 对接 CDN
基于上⾯的配置构建出来的结果,浏览器在加载资源的时候,都是使⽤的根路径(/)加载,如果使⽤ CDN 的话会出现资源加载 404 的问题。
我们可以配置base来设置基础路径,类似于 webpack 的PUBLIC_PATH。
export default defineConfig({
base: '/some/public/path',
})
4. 构建出错
4.1 不到包
报错信息为:
[plugin: vite:dep-scan] Failed to resolve entry for package "xxx"
通常是依赖包未在 package.json 正确配置 main、module 等字段,导致 vite ⽆法到包的⼊⼝。
可以设置通过设置别名的⽅式,将其映射到正确的⽂件上。
export default defineConfig({
resolve: {
alias: [{
find: /^SOME_PACKAGE_NAME$/,
replacement: 'SOME_PACKAGE_NAME/dist/xxx.es.js',
}],
},
});
4.2 请求超时
报错信息为:
net::ERR_ABORTED 408 (Request Timeout)
启动开发服务器后,浏览器出现请求超时错误。是因为 vite 检测到对依赖包的请求,且该依赖尚未被 vite 处理过,这时候会会触发预构建,导致请求超时以及页⾯重载。
我们可以多刷新⼏次等 vite 完成预构建,也可以将依赖加⼊optimizeDeps.include来提前处理。
4.3 导⼊模块出错
报错信息为:
Internal server error: Failed to resolve import "./chunk-7L3SPMWF.js" from "node_modules/.vite/antd.js?
v=7bec0e27". Does the file exist?
可能是因为⼀些依赖包输出的格式 vite 还不⽀持,可以看看这个。
这个错误只在开发服务器运⾏处理过程中存在,待页⾯正常展⽰后就不出现了,忽略这个错误之后,⽬前看也没产⽣什么影响。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论