Umijs4.xx如何自定打包路径

1,226 阅读1分钟

最近公司新做了项目,通过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
image.png 显然不符合项目要求的打包路径。

二、自定定义打包

在项目根目录下新建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 命令打包目录如下图

image.png

但是上生产发布的时候可能会出现问题,因为打包的index.html引入的js资源在head标签内,非异步加载。

image.png

三、打包异步引入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 $;
  });
};

打包后如图

image.png 我这是只针对umi.js在index.html的引入,如果需要在所有的js引入中加defer属性,可以去掉对应的判断逻辑。