美文网首页vue开发干货
在vue-cli 3.0 中根据不同环境动态注入CDN

在vue-cli 3.0 中根据不同环境动态注入CDN

作者: yichen_china | 来源:发表于2019-03-26 20:02 被阅读46次

    前言:一名内孤的博文vue-cli 3.0 build包太大导致首屏过长的解决方案中提到了CDN优化,之前是直接在html中手动注入JS,也没有对开发和生产模式进行区分,因为是使用收费的CDN,所以在开发模式会遇到无权使用CDN的问题。要是使用CDN写死在html中,不同环境需要手动的切换CDN,那么早晚有一天会搞乱,下面就说说怎么在vue-cli 3.0 中根据不同环境动态注入CDN。

    1. 修改public/index.html

    通过htmlwebpackplugin动态注入脚本和样式,index.html如下:

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width,initial-scale=1.0">
        <link rel="icon" href="<%= BASE_URL %>favicon.ico">
        <title>杭州纳舍科技</title>
        <!-- 使用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>
        <noscript>
          <strong>We're sorry but ui doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
        </noscript>
        <div class="global-loading">
          <div class="spinner"></div>
        </div>
        <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>
    
    

    2. 修改vue.config.js配置

    首先我们会考虑哪些东西要进行CDN优化,例如我们需要把vue、vue-router、moment在构建的时候排除在外使用CDN加载这三个库,那么需要把添加externals

    const isProduction = process.env.NODE_ENV === 'production';
    module.exports = {
      configureWebpack: config => {
        if (isProduction) {
          config.externals = {
            'vue': 'Vue',
            'vue-router': 'VueRouter',
            'moment': 'moment'
          }
        }
      }
    }
    
    

    现在我们运行npm run build 打包出来的文件就没有Vue、VueRouter、moment,现在我们使用html-webpack-plugin插件进行动态注入CDN,在vue-cli 3.0 中我们要这样配置:

    const isProduction = process.env.NODE_ENV === 'production';
    const cdn = {
      css: ['xxx.css', 'sss.js'],
      js: ['xxxx.js', 'sss.js']
    }
    module.exports = {
      configureWebpack: config => {
        if (isProduction) {
          config.externals = {
            'vue': 'Vue',
            'vue-router': 'VueRouter',
            'moment': 'moment'
          }
        }
      }
      chainWebpack: config => {
        if (isProduction) {
          config.plugin('html')
          .tap(args => {
              args[0].cdn = cdn;
            return args;
          })
        }
      }
    }
    
    

    到目前为止已经解决了开发模式不使用CDN,生产模式使用CDN的问题和动态在html中注入CDN的问题。

    可能你会遇到和我一样的问题

    预发布build测试,但无权使用生产上的CDN问题,那么我们必须再添加一个环境变量来区分预发布build的模式。(vue-cli 3.0 环境变量文档)这里我添加一个IS_LOCAL_BUILD,首先我们在vue.cofnig.js同路径下创建一个.en.production.local :

    // .en.production.local` 内容:
    IS_LOCAL_BUILD = 'isLocalBuild'
    
    

    修改vue.config.js如下:

    const isProduction = process.env.NODE_ENV === 'production';
    const isLocalBuild = process.env.IS_LOCAL_BUILD === 'isLocalBuild';
    const JS_CDN = isLocalBuild ? [
      预发布CDN(例如那些免费的CDN)
    ] : [
      生产环CDN
    ];
    const CSS_CDN = isLocalBuild ? [预发布CDN]: [生产CDN]
    const cdn = {
      css: CSS_CDN,
      js: JS_CDN
    }
    module.exports = {
      configureWebpack: config => {
        if (isProduction) {
          config.externals = {
            'vue': 'Vue',
            'vue-router': 'VueRouter',
            'moment': 'moment'
          }
        }
      }
      chainWebpack: config => {
        if (isProduction) {
          config.plugin('html')
          .tap(args => {
              args[0].cdn = cdn;
            return args;
          })
        }
      }
    }
    
    

    ok,上面区分了生产、预发布和开发环境使用CDN的问题,这样就不用根据不同环境手动去修改CDN了。不过又一点要注意:⚠️预发布版本的构建才需要添加.en.production.local

    完整的vue.config.js(供参考)

    const path = require('path');
    const CompressionWebpackPlugin = require('compression-webpack-plugin');
    const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
    const productionGzipExtensions = ['js', 'css'];
    const isProduction = process.env.NODE_ENV === 'production';
    
    function resolve(dir) {
      return path.join(__dirname, dir);
    }
    
    // 预发布环境
    const isLocalBuild = process.env.IS_LOCAL_BUILD === 'isLocalBuild';
    console.log('前端文件预发布打包- isLocalBuild:', isLocalBuild);
    
    // 非externals CND前缀设置
    const CDN_URL = isLocalBuild ? '/' : '//s.zypj.nasetech.com/';
    
    // 区分生产环境打包和预发布打包,使用不同的CDN
    const JS_CDN = isLocalBuild ? [
      // 预发布CDN
    ] : [
      // 生产CDN
    ];
    
    const cdn = {
      // css: [],
      js: JS_CDN
    }
    
    module.exports = {
      lintOnSave: true,
      baseUrl: isProduction ? CDN_URL : '/',
      chainWebpack: (config) => {
        // build打包才使用CDN
        if (isProduction) {
          config.plugin('html')
          .tap(args => {
              args[0].cdn = cdn;
            return args;
          })
        }
    
        config.resolve.alias
          .set('assets', resolve('src/assets'))
          .set('pages', resolve('src/pages'))
          .set('components', resolve('src/components'))
          .set('utils', resolve('src/utils'))
      },
      devServer: {
        host: '0.0.0.0',
        port: 8080,
        https: false,
        hotOnly: false,
        disableHostCheck: false,
        proxy: {
          '/api/v0/': {
            // 目标 API 地址
            target: 'http://127.0.0.1:4545',
            // 将主机标头的原点更改为目标URL
            changeOrigin: true,
          },
        },
      },
      configureWebpack: config => {
        // 生产模式
        if (isProduction) {
          config.externals = {
            'vue': 'Vue',
            'vue-router': 'VueRouter',
            'moment': 'moment'
          }
          // 打包生产.gz包
          config.plugins.push(new CompressionWebpackPlugin({
            algorithm: 'gzip',
            test: new RegExp('\\.(' + productionGzipExtensions.join('|') + ')$'),
            threshold: 10240,
            minRatio: 0.8
          }))
          // 添加自定义代码压缩配置
          config.plugins.push(
            new UglifyJsPlugin({
              uglifyOptions: {
                compress: {
                  warnings: false,
                  drop_debugger: true,
                  drop_console: true,
                },
              },
              sourceMap: false,
              parallel: true,
            })
          )
        }
      }
    }
    
    

    * 使用CDN一些有意思的坑:

    使用CDN还会遇到一些有意思的事,例如使用beta版的vue导致element UI库有些组件无法正常工作; 使用免费的CDN上线没有多久就GG不能用等悲惨故事!!!

    作者:内孤
    链接:https://www.jianshu.com/p/9d6c1efebcd9
    来源:简书
    简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

    相关文章

      网友评论

        本文标题:在vue-cli 3.0 中根据不同环境动态注入CDN

        本文链接:https://www.haomeiwen.com/subject/kznnvqtx.html