webpack 打包优化 cdn加速, 分包, 异步组件

1,060 阅读2分钟

优化前: all:251.42KB image.png 优化后:109.58KB image.png

准备工作

安装webpack-bundle-analyzer

使用webpack-bundle-analyzer 使打包结果可视化

创建文件 touch webpack.config.js,导入到vue.config.js, 使Vue 使用webpack 插件

const BundleAnalyzerPlugin = require("webpack-bundle-analyzer")
  .BundleAnalyzerPlugin;

// 当前环境为生产环境使用此配置
if (process.env.NODE_ENV === "production") {
  module.exports = {
     // 不生成source map 文件
    devtool: "none",
    plugins: [new BundleAnalyzerPlugin()],
    // 不要导入以下库 vue vuex vue-router
    externals: {
      vue: "Vue",
      vuex: "Vuex",
      "vue-router": "VueRouter",
      axios: "axios",
    },
  };
} else {
  module.exports = {};
}

vue.config.js 导入webpack.config

// vue-cli的配置文件
module.exports = {
  devServer: {
    proxy: {
      "/api": {
        target: "http://test.my-site.com",
      },
    },
  },
  configureWebpack: require("./webpack.config"),
};

1. 使用CDN

我们在webpack 配置了在生产环境中不要使用指定的库, 我们在public/index.html 引入cdn,使打包结果进一步降低,且请求会更快

CDN 链接:BootCDN

    <!-- ref cdn -->
    <% if(NODE_ENV==="production" ){%>
        <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.11/vue.min.js"></script>
        <script src="https://cdn.bootcdn.net/ajax/libs/vuex/3.6.2/vuex.min.js"></script>
        <script src="https://cdn.bootcdn.net/ajax/libs/vue-router/3.4.9/vue-router.min.js"></script>
        <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.0/axios.min.js"></script>
    <% } %>
    <!-- built files will be auto injected -->

vue-cli 使用了copy-webpack-plugin  Webpack 插件,用于将文件或者目录从源路径复制到目标路径,最终的index.html 就是使用了public/index.html 为模板的,我们使用模板语法

<% if(NODE_ENV==="production" ){%>
.....
<% } %>

插件会识别当前的运行环境是否为生产环境,如果为生产环境就使用CDN 否则使用本地库加载.

!!! 使用CDN 注意

由于使用CDN 会全局导入,会使Vue,Vuex,VueRouter,axios被注入到全局 image.png 因此代码就不需要Vue.use(...) 使用插件,因此需要添加一个判断,如果有全局函数就不安装插件了

if (!window.Vuex) {
  install(Vue);
}
.... 同理
if (!window.VueRouter) {
  Vue.use(VueRouter); // 使用一个vue插件
}

2. 按需加载库

使用具名到处使用的函数,例如Vuex. import { install, Store } from "vuex"; 使用install(Vue) 使用插件, new Store 插件仓库,可以减少打包体积

3. 分包

使用 import 函数来异步加载路由组件,将路由组件分散到不同的包中。例如:

const Foo = () => import(/* webpackChunkName: "foo" */ './Foo.vue')
const Bar = () => import(/* webpackChunkName: "bar" */ './Bar.vue')

const router = new VueRouter({
  routes: [
    { path: '/foo', component: Foo },
    { path: '/bar', component: Bar }
  ]
})

上述代码中,import 函数用于异步加载 Foo.vue 和 Bar.vue 两个路由组件,并将它们分散到名为 foo 和 bar 的不同包中。通过这种方式,可以将路由组件分割成多个包,从而减小首屏加载时间,提高页面加载速度和性能。

4. vue modern

由于vue-cli 默认使用了babel, 会使打包结果有更多的兼容代码,但有的现代浏览器不需要兼容,因此需要按浏览器是否现代进行分别打包.

vue-cli-service build --modern

使用modern 会使打包结果的html 应用以下link

image.png 由于旧浏览器不支持 type=module 因此会加载 14,15行的,而现代浏览器可以识别nomodule 知道它是旧浏览器的因此不会引用