// config/cdn.js

const cdn = {
  css: [
    // 'https://cdn.jsdelivr.net/npm/vant@2.8/lib/index.css'
  ],
  js: [
    'https://cdn.bootcss.com/vue/2.5.2/vue.min.js',
    'https://cdn.bootcss.com/vue-router/3.0.1/vue-router.min.js',
    'https://cdn.bootcss.com/vuex/3.0.1/vuex.min.js'
  ]
}

module.exports = cdn
// webpack.config.js

plugins: [
  new HtmlWebpackPlugin(Object.assign({
    filename: 'index.html',
    template: 'index.html',
    inject: true
  }, config.cdn))
]
<!--index.html-->

<body>
  <div id="app">
    <!-- shell -->
  </div>
  <script src="./static/js/axios.min.js"></script>
  <% for (var i in htmlWebpackPlugin.options.js&&htmlWebpackPlugin.options.js) { %>
  <script src="<%= htmlWebpackPlugin.options.js[i] %>"></script>
  <% } %>
  <!-- built files will be auto injected -->
</body>

VueCLI3打包优化--CDN

  1. vue.config.js下的配置如下

      externals: [
             {
                 'vue': 'Vue',
                 'vue-router': 'VueRouter',
                 'vuex': 'Vuex',
                 'element-ui': 'ELEMENT',
                 'echarts': 'echarts',
                 'vue-echarts': 'VueECharts',
                 'moment': 'moment',
                 'axios': 'axios',
             },  
            // vue-echarts引入的方式,需要如下去抽离
             'echarts/lib/echarts',
             /^echarts\/lib\/chart\/.+$/i,
             /^echarts\/lib\/component\/.+$/i,
         ]
  2. 配置CDN

    const cdn = {
     js: ['https://lib.baomitu.com/echarts/4.9.0-rc.1/echarts.min.js',
         'https://lib.baomitu.com/vue-echarts/5.0.0-beta.0/vue-echarts.min.js',
         'https://lib.baomitu.com/vue/2.6.10/vue.min.js',
         'https://lib.baomitu.com/vuex/3.1.0/vuex.min.js',
         'https://lib.baomitu.com/vue-router/3.0.6/vue-router.min.js',
         'https://lib.baomitu.com/moment.js/2.29.1/moment.min.js',
         'https://lib.baomitu.com/element-ui/2.15.1/index.min.js'],
     css: ['https://lib.baomitu.com/element-ui/2.15.1/theme-chalk/index.min.css']
    }
    module.exports = {
     configureWebpack:{......},
    chainWebpack(config) {
     config.plugin('html').tap(opts => {
             opts[0].cdn = cdn;
             return opts
         })
      }
    }
    

    可根据环境变量,仅在线上采取使用CDN,开发环境直接使用npm依赖包即可。

    const IsProd= process.env.NODE_ENV === 'production';
    
    chainWebpack(config) {
     if (IsProd) {
         config.plugin('html').tap(opts => {
             opts[0].cdn = cdn;
             return opts
         })
      }
    }

    3.index.html文件

    <!DOCTYPE html>
    <html lang="en">
     <!-- 使用CDN的CSS文件 -->
     <% for (var i in htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.css) { %>
       <link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="preload" as="style">
       <link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="stylesheet">
     <% } %>
     <!-- 使用CDN的JS文件 -->
     <% for (var i in htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.js) { %>
       <link href="<%= htmlWebpackPlugin.options.cdn.js[i] %>" rel="preload" as="script">
     <% } %>
      </head>
      <body>
     <div id="app"></div>
     <!-- built files will be auto injected -->
     <% for (var i in htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.js) { %>
       <script src="<%= htmlWebpackPlugin.options.cdn.js[i] %>"></script>
     <% } %>
      </body>
    </html>

    使用 CDN 加速优化

    const isProduction = process.env.NODE_ENV === 'production';
     
    // externals
    const externals = {
      vue: 'Vue',
      'vue-router': 'VueRouter',
      vuex: 'Vuex',
      vant: 'vant',
      axios: 'axios'
    }
    // CDN 外链,会插入到 index.html 中
    const cdn = {
      // 开发环境
      dev: {
     css: [],
     js: []
      },
     // 生产环境
      build: {
     css: ['https://cdn.jsdelivr.net/npm/vant@2.12/lib/index.css'],
     js: [
       'https://cdn.jsdelivr.net/npm/vue@2.6.11/dist/vue.min.js',
       'https://cdn.jsdelivr.net/npm/vue-router@3.1.5/dist/vue-router.min.js',
       'https://cdn.jsdelivr.net/npm/axios@0.19.2/dist/axios.min.js',
       'https://cdn.jsdelivr.net/npm/vuex@3.1.2/dist/vuex.min.js',
       'https://cdn.jsdelivr.net/npm/vant@2.12/lib/vant.min.js'
     ]
      }
    }
    module.exports = {
      configureWebpack: config => {
     // 为生产环境修改配置...
     if (isProduction) {
       // externals
       config.externals = externals
     }
      },
      chainWebpack: config => {
     /**
      * 添加 CDN 参数到 htmlWebpackPlugin 配置中
      */
     config.plugin('html').tap(args => {
       if (isProduction) {
         args[0].cdn = cdn.build
       } else {
         args[0].cdn = cdn.dev
       }
       return args
     })
      }
    }
  <!-- 使用 CDN 的 CSS 文件 -->
    <% for (var i in htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.css) { %>
      <link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="preload" as="style" />
      <link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="stylesheet" />
    <% } %>
     <!-- 使用 CDN 加速的 JS 文件,配置在 vue.config.js 下 -->
    <% for (var i in htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.js) { %>
      <script src="<%= htmlWebpackPlugin.options.cdn.js[i] %>"></script>
    <% } %>

打包前的处理

build/utils.js添加读取事件

使用cdn其实也就是在webpack热启动和打包项目的时候动态插入script和style链接,为了方便维护,我们通过在build/utils.js文件上添加几个方法

1.添加cdn根地址

按照规律,得出cdn资源路径规则为
https://cdn.bootcss.com + 模块名 + 版本号 + 具体路径

// build/utils.js 国内免费cdn镜像源
exports.cdnBaseHttp = 'https://cdn.bootcss.com';

2.添加cdn模块 按照需要删改

//  build/utils.js external配置
exports.externalConfig = [
  { name: 'vue', scope: 'Vue', js: 'vue.min.js' },
  { name: 'vue-router', scope: 'VueRouter', js: 'vue-router.min.js' },
  { name: 'axios', scope: 'axios', js: 'axios.min.js' },
  { name: 'element-ui', scope: 'ELEMENT', js: 'index.js', css: 'theme-chalk/index.css' },
];

name 模块名称,与package.json同名
scope 模块作用域命名
js js地址
css css地址

这里特别注意scope,它是webpack配置的external参数下的信息,比如vue的作用域命名是Vue,vue-router的作用域命名是VueRouter,element-ui的作用域命名是ELEMENT,同理,jq的作用域命名是JQuery,具体做法是先引入该资源,然后在控制台依次输入近似的值,一个个匹配(目前没找到更好的做法)。

3.添加获取版本号方法

// build/utils.js 获取模块版本号
exports.getModulesVersion = () => {
  let mvs = {};
  let regexp = /^npm_package_.{0,3}dependencies_/gi;
  for (let m in process.env) { // 从node内置参数中读取,也可直接import 项目文件进来
    if (regexp.test(m)) { // 匹配模块
       // 获取到模块版本号
      mvs[m.replace(regexp, '').replace(/_/g, '-')] = process.env[m].replace(/(~|\^)/g, '');
    }
  }
  return mvs;
};

4.导出不需要被打包的cdn模块配置重点

// build/utils.js
exports.getExternalModules = config => {
  let externals = {}; // 结果
  let dependencieModules = this.getModulesVersion(); // 获取全部的模块和版本号
  config = config || this.externalConfig; // 默认使用utils下的配置
  config.forEach(item => { // 遍历配置
    if (item.name in dependencieModules) {
      let version = dependencieModules[item.name];
      // 拼接css 和 js 完整链接
      item.css = item.css && [this.cdnBaseHttp, item.name, version, item.css].join('/');
      item.js = item.js && [this.cdnBaseHttp, item.name, version, item.js].join('/');
      externals[item.name] = item.scope; // 为打包时准备
    } else {
      throw new Error('相关依赖未安装,请先执行npm install ' + item.name);
    }
  });
  return externals;
};

_____
56 声望0 粉丝