4

前言

问题

动态设置publicpath

为什么会有这个需求?
一些异步的静态资源(例如打包后的chunk.css,chunk.js),是指向当前请求server的地址的,而不是我们期望的静态资源服务器,所以我们要配置publicpath,打包的时候指定请求的静态资源服务器地址
问题来了:
我们有很多的环境,dev,test,uat,prd,
你总不能发布每个环境前,打不同的publicpath包吧?
那么我们就需要动态配置publicpath
webpack给我们留了一条后路,
webpack_public_path
按照文档所说,
我们配置下
__webpack_public_path__ = process.env.ASSET_PATH;
然后在main.js或者index.js 的首行代码加载就好了,因为要在加载动态组件之前进行配置。
一般情况下,我们的首行代码为
import App from "./App"
大家也都知道 import 和 require的区别
import 是 编译时导入,会有“提升现象”

    __webpack_public_path__ = "http://cdn.com";
    import App from "./App" 

实际上在打包编译时为

    import App from "./App" 
    __webpack_public_path__ = "http://cdn.com";

那么组件加载 是在 我们publicPath 之前,那么我们配置publicPath也就失去了意义。
所以 我们变通一下

    // publicpath.js
    __webpack_public_path__ = "http://cdn.com";

这样就解决了

    import  "./publicpath.js" 
    import App from "./App" 

另外上述只是配置publicpath,动态配置的话 需要 服务器template模版将当前环境的静态资源服务器地址配置

<script>
window.publicpath = "http://test.cdn.com"
</script>
    // publicpath.js
    __webpack_public_path__ = window.publicpath;

注意一点,__webpack_public_path__是webpack的内部全局参数,而不是window对象的属性,所以不要多此一举写成“window.__webpack_public_path__”

使用typescript的同学,eslint 会error,
你改成

    // publicpath.js
    (__webpack_public_path__ as any) = "http://cdn.com";

就不会报错了。

记住,有可能你的配置使用了"Tree shaking"

这样,你的publicpath.js虽然import了,但是其实并没有使用其中任何成员,那么webpack将不会将publicpath.js打包进去,你的__webpack_public_path__也就不会生效,可以在package.json配置sideEffects属性,具体请查询Tree shaking.

固定打包内容中的1.chunk.js

    filename: 'static/js/bundle.[hash].js',
    chunkFilename: 'static/js/[name].chunk.js',

这样就可以保证 分离出来的 chunk.js 和 bundle.js 都是有名字的
但是会有特殊的模块没有名字,就会使用 module-id 作为name

我们需要配置 webpack 将其他共用的 "number".chunk.js
整合在一起,这样引用的时候 不用经常改名字。比如全部整合成vendors.chunks.js

plugin中添加

+      new webpack.HashedModuleIdsPlugin()

optimization中添加

splitChunks: {
        cacheGroups: {
          vendor: {
            test: /[\\/]node_modules[\\/]/,
            name: 'vendors',
            chunks: 'all'
          }
        }
      },

bundle分析

分析output文件中的成分,从而可以进行优化打包内容,进一步缩减打包size,在webpack plugin中添加BundleAnalyzerPlugin

new BundleAnalyzerPlugin()

打包的时候 就会启动本地服务 ,并且展示各个 模块的大小和内容。

借用第三方cdn

在bundle分析之后,我们可以看到 moment.js,axios等等第三方库占据了一定大小,我们可以通过 第三方cdn引入,

import moment from "moment"

改变为

const moment = window.moment;

小结


ThenMorning
190 声望18 粉丝

但行好事,莫问前程.