最近公司新做了项目,通过mPaas静态资源发布,要把H5静态资源打包路径按照要求进行划分js、css、img路径。项目是基于umi4.2+react18搭建的。 要求打包路径
|-- www
| -- static
| -- img
| -- xxx.png
| -- ....png
| -- js
| -- xxx.js
| -- ....js
| -- css
| -- xxx.css
| -- ....css
| -- index.html
一、项目初始化打包路径
项目初始化打包路径如下所示
|-- dist
| -- static
| -- xxx.png
| -- 1xxx.js
| -- 2xxx.js
| -- .....js
| -- 1xxx.css
| -- 2xxx.css
| -- ....css
| -- index.html
二、自定定义打包
在项目根目录下新建config文件夹里创建config.js,umi会默认读取到该配置的。不创建config/config.js也可以,可以在根目录创建umirc.js,如果两个文件同时存在,umirc.js的优先级要比config/config.js的优先级高。如果后期配置过多,还是建议创建config/config.js. config.js的配置如下
//config.js
import { defineConfig } from "umi";
import ChainWebpack from "./configTools/chainWebpack";
const isDev = process.env.NODE_ENV === 'development';
const config = isDev?'':ChainWebpack
export default defineConfig({
outputPath: 'www',
chainWebpack:config,
});
在config.js的同级目录下创建configTools目录,存放配置等,我这里用到了ChainWebpack配置,我在configTools文件下创建了ChainWebpack.js然后在config.js内引入
//ChainWebpack.js
const staticDir = 'static';
const ChainWebpack = (config, { webpack, env }) => {
// 修改css输出目录
config.plugin('mini-css-extract-plugin').tap((args) => [
{
...args[0],
filename: `${staticDir}/css/[name].[contenthash:8].css`,
chunkFilename: `${staticDir}/css/[name].[contenthash:8].chunk.css`,
},
]);
// 修改js输出目录
config.output
.filename(`${staticDir}/js/[name].[hash:8].js`)
.chunkFilename(`${staticDir}/js/[name].[contenthash:8].chunk.js`);
// 修改image输出目录
config.output.set('assetModuleFilename', `${staticDir}/images/[name].[contenthash:8][ext]`);
return config;
};
export default ChainWebpack;
到这里基本上已经结束了,运行npm run build 命令打包目录如下图
但是上生产发布的时候可能会出现问题,因为打包的index.html引入的js资源在head标签内,非异步加载。
三、打包异步引入js文件
查了好多资料和官方文档,都是要确定引入js的路径和名称。因为打包出的静态资源要加hash,所以不能采用。最后查阅官方文档发现Umi提供的插件API有一个modifyHTML,可以操作打包后的html. 在项目根路下创建plugin.ts文件(一定要是ts文件)
//plugin.ts
import { IApi } from "umi";
export default (api: IApi) => {
api.modifyHTML(($) => {
$("script").attr("src", (index, src) => {
if (src.includes("umi")) {
$("script").eq(0).attr("defer", "ture");
}
return src;
});
return $;
});
};
打包后如图
我这是只针对umi.js在index.html的引入,如果需要在所有的js引入中加defer属性,可以去掉对应的判断逻辑。