美文网首页前端
vue-cli3 之vue.config.js配置

vue-cli3 之vue.config.js配置

作者: 取个帅气的名字真好 | 来源:发表于2019-04-24 23:00 被阅读0次

    1、 cdn、全局cdn(所有的js、css都使用cdn)
    2、Gzip压缩(压缩js、css)
    3、去掉注释、去掉console.log
    4、压缩图片
    5、本地代理
    6、环境变量和模式

    基本配置

    const path = require('path')
    function resolve (dir) {
      return path.join(__dirname, './', dir)
    }
    module.exports = {
      publicPath:  '/', // 默认'/',部署应用包时的基本 URL
      outputDir: 'dist',
      assetsDir: '', // 相对于outputDir的静态资源(js、css、img、fonts)目录
      runtimeCompiler: true, // 是否使用包含运行时编译器的 Vue 构建版本
      productionSourceMap: false, // 生产环境的 source map
      configureWebpack: config => {},
      chainWebpack: config => {}
    }
    

    一、cdn、全局cdn(所有的js、css都使用cdn)

    vue.config

    // cdn预加载使用
    const externals = {
      'vue': 'Vue',
      'vue-router': 'VueRouter',
      'vuex': 'Vuex',
      'axios': 'axios',
      'element-ui': 'ELEMENT',
      'js-cookie': 'Cookies',
      'nprogress': 'NProgress'
    }
    const cdn = {
      // 开发环境
      dev: {
        css: [
          'https://unpkg.com/element-ui/lib/theme-chalk/index.css',
          'https://cdn.bootcss.com/nprogress/0.2.0/nprogress.min.css'
        ],
        js: []
      },
      // 生产环境
      build: {
        css: [
          'https://unpkg.com/element-ui/lib/theme-chalk/index.css',
          'https://cdn.bootcss.com/nprogress/0.2.0/nprogress.min.css'
        ],
        js: [
          'https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.min.js',
          'https://cdn.jsdelivr.net/npm/vue-router@3.0.1/dist/vue-router.min.js',
          'https://cdn.jsdelivr.net/npm/vuex@3.0.1/dist/vuex.min.js',
          'https://cdn.jsdelivr.net/npm/axios@0.18.0/dist/axios.min.js',
          'https://unpkg.com/element-ui/lib/index.js',
          'https://cdn.bootcss.com/js-cookie/2.2.0/js.cookie.min.js',
          'https://cdn.bootcss.com/nprogress/0.2.0/nprogress.min.js'
        ]
      }
    }
    configureWebpack: config => {
       const myConfig = {}
        //本地环境 线上环境
        if(process.env.NODE_ENV === 'production'){
          myConfig.externals  = externals
        }
        if(process.env.NODE_ENV === 'development'){
          myConfig.devServer = {
            disableHostCheck: true
          }
        }
        return myConfig
    }
    
    
    chainWebpack: config => {
            // 使用cdn
          config.plugin('html').tap(args => {
            if (process.env.NODE_ENV === 'production') {
              args[0].cdn = cdn.build
            }
            if (process.env.NODE_ENV === 'development') {
              args[0].cdn = cdn.dev
            }
            return args
          })
    }
    

    public/index.html

    <!DOCTYPE html>
    <html lang="zh-CN">
    
    <head>
      <meta charset="utf-8">
      <meta name="renderer" content="webkit">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <link rel="icon" href="<%= BASE_URL %>favicon.ico">
    
      <!-- 使用CDN加速的CSS文件,配置在vue.config.js下 -->
      <% 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) { %>
      <link href="<%= htmlWebpackPlugin.options.cdn.js[i] %>" rel="preload" as="script">
      <% } %>
    
      <!-- 测试 -->
      <title>vue-cli3</title>
    </head>
    
    <body>
    
      <noscript>
        <strong>We're sorry but vue-project-demo doesn't work properly without JavaScript enabled. Please enable it
          tocontinue.</strong>
      </noscript>
      <div id="app"></div>
    
      <!-- 使用CDN加速的JS文件,配置在vue.config.js下 -->
      <% for (var i in htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.js) { %>
      <script src="<%= htmlWebpackPlugin.options.cdn.js[i] %>"></script>
      <% } %>
    
    </body>
    </html>
    

    npm run build 一下, 使用本地预览
    serve -s dist打开控制台,如下图

    cdn

    全局cdn
    使用七牛云融合 CDN

    1、安装Node.js SDK

    $ npm install qiniu
    

    2、获取密钥(Access/Secret Key)


    Access/Secret Key

    3、新建upcdn.js

    const qiniu = require('qiniu')
    const glob = require('glob')
    const mime = require('mime')
    const path = require('path')
    
    const isWindow = /^win/.test(process.platform)
    
    let pre = path.resolve(__dirname, './dist/') + (isWindow ? '\\' : '')
    
    const files = glob.sync(
      `${path.join(
        __dirname,
        './dist/**/*.?(js|css|map|png|jpg|svg|woff|woff2|ttf|eot)'
      )}`
    )
    pre = pre.replace(/\\/g, '/')
    
    const options = {
      scope: 'test2' // 空间对象名称 
    }
    var config = {
      qiniu: {
        accessKey: '你的AccessKey',  // 个人中心 秘钥管理里的 AccessKey
        secretKey: '你的SecretKey',  // 个人中心 秘钥管理里的 SecretKey
        bucket: options.scope,
        domain: 'http://ppqqg4jtj.bkt.clouddn.com' //你的域名
      }
    }
    var accessKey = config.qiniu.accessKey
    var secretKey = config.qiniu.secretKey
    
    var mac = new qiniu.auth.digest.Mac(accessKey, secretKey)
    var putPolicy = new qiniu.rs.PutPolicy(options)
    var uploadToken = putPolicy.uploadToken(mac)
    var cf = new qiniu.conf.Config({
      zone: qiniu.zone.Zone_z2
    })
    var formUploader = new qiniu.form_up.FormUploader(cf)
    async function uploadFileCDN (files) {
      files.map(async file => {
        const key = getFileKey(pre, file)
        try {
          await uploadFIle(key, file)
          console.log(`上传成功 key: ${key}`)
        } catch (err) {
          console.log('error', err)
        }
      })
    }
    async function uploadFIle (key, localFile) {
      const extname = path.extname(localFile)
      const mimeName = mime.getType(extname)
      const putExtra = new qiniu.form_up.PutExtra({ mimeType: mimeName })
      return new Promise((resolve, reject) => {
        formUploader.putFile(uploadToken, key, localFile, putExtra, function ( respErr, respBody, respInfo) {
          if (respErr) {
            reject(respErr)
          }
          resolve({ respBody, respInfo })
        })
      })
    }
    function getFileKey (pre, file) {
      console.log(pre, file);
      
      if (file.indexOf(pre) > -1) {
        const key = file.split(pre)[1]
        return key.startsWith('/') ? key.substring(1) : key
      }
      return file
    }
    
    (async () => {
      console.time('上传文件到cdn')
      await uploadFileCDN(files)
      console.timeEnd('上传文件到cdn')
    })()
    
    
    

    4、vue.config.js

    const cdnDomian = 'http://ppqqg4jtj.bkt.clouddn.com' //静态文件cdn
    module.exports = {
      publicPath:  cdnDomian, // 默认'/',部署应用包时的基本 URL
    }
    

    5、package.json

      "scripts": {
        "serve": "vue-cli-service serve",
        "build": "vue-cli-service build",
        "analyz": "vue-cli-service build --mode analyz",
        "lint": "vue-cli-service lint",
        "upcdn": "node ./upcdn.js",
        "globalcdn": "rm -rf dist && echo --- 正在打包... --- && npm run build && echo --- 打包完成 --- && echo --- 正在上传到服务器... --- && npm run upcdn &&  echo -- 上传完成!!"
      },
    

    执行npm run globalcdn 效果如下图

    效果1 效果2

    二、Gzip压缩(压缩js、css)

    1、安装compression-webpack-plugin

    npm i compression-webpack-plugin
    

    2、vue.config.js

    // gzip --start
    const CompressionWebpackPlugin = require('compression-webpack-plugin')
    const productionGzip = true // 是否使用gzip
    const productionGzipExtensions = ['js', 'css'] // 需要gzip压缩的文件后缀
    // gzip --end
    
    module.exports = {
        configureWebpack: config => {
             if (process.env.NODE_ENV === 'production') {
          // gzip
          //  构建时开启gzip,降低服务器压缩对CPU资源的占用,服务器也要相应开启gzip
          productionGzip && myConfig.plugins.push(
            new CompressionWebpackPlugin({
              test: new RegExp('\\.(' + productionGzipExtensions.join('|') + ')$'),
              threshold: 8192,
              minRatio: 0.8
            })
          )
      }
    
    
        }
    
    }
    

    3、后台Nginx配置

    gzip on;
    gzip_static on;
    gzip_min_length 1024;
    gzip_buffers 4 16k;
    gzip_comp_level 2;
    gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php application/vnd.ms-fontobject font/ttf font/opentype font/x-woff image/svg+xml;
    gzip_vary off;
    gzip_disable "MSIE [1-6]\.";
    
    本地预览效果
    带有.gz后缀说明压缩成功了

    线上在 response headers 里会有一个Content-Encoding:gzip

    三、去掉注释、去掉console.log

    1、安装uglifyjs-webpack-plugin

    npm i uglifyjs-webpack-plugin
    

    2、vue.config.js

    const UglifyJsPlugin = require('uglifyjs-webpack-plugin') // 去掉注释
    module.exports = {
        configureWebpack: config => {
              const myConfig = {}
              if (process.env.NODE_ENV === 'production') {
              myConfig.plugins = []
              // 去掉注释
              // 去掉注释
              myConfig.plugins.push(
                new UglifyJsPlugin({
                  uglifyOptions: {
                    output: {
                      comments: false, // 去掉注释
                    },
                    compress: {
                      warnings: false,
                      drop_console: true,
                      drop_debugger: false,
                      pure_funcs: ['console.log']//移除console
                  }
                  }
                })
              )
    
          }
      }
    }
    

    四、压缩图片

    1、安装image-webpack-loader

    npm i -D image-webpack-loader
    

    2、vue.congin.js

    module.exports = {
      chainWebpack: config => {
          // 压缩图片
        config.module
          .rule('images')
          .use('image-webpack-loader')
          .loader('image-webpack-loader')
          .options({
            mozjpeg: { progressive: true, quality: 65 },
            optipng: { enabled: false },
            pngquant: { quality: '65-90', speed: 4 },
            gifsicle: { interlaced: false },
            webp: { quality: 75 }
          })
      }
    }
    

    五、环境变量和模式、本地代理

    .env.production文件 (线上)

    NODE_ENV = 'production'
    
    VUE_APP_SRC='https://www.google.com'
    VUE_APP_V='https://www.google.com'
    

    .env.development文件

    //开发环境
    NODE_ENV='development'
    
    VUE_APP_SRC=''http://192.168.1.174:8003'
    VUE_APP_V='http://192.168.1.173:8003'
    
    module.exports = {
      devServer: {
        open: true, // 自动启动浏览器
        host: '0.0.0.0', // localhost
        port: 8080, // 端口号
        https: false,
        hotOnly: false, // 热更新
        proxy: {
          // 本地代理包含user的接口 如: /user/getUser 
          '^/user': {
            target: process.env.VUE_APP_SRC,
            ws: true,   //开启WebSocket
            changeOrigin: true
          },
          '^/v1': {  //匹配包含 /v1的接口  如:v1/xxx/xx
            target: process.env.VUE_APP_V,
            ws: true,
            changeOrigin: true
          }
        }
      },
    }
    

    完整代码

    const path = require('path')
    const IS_PROD = ['production'].includes(process.env.NODE_ENV)
    const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin // 打包分析
    
    const mockIndexData = require('./src/mock/index.json') // mock.js (传说的假数据)
    
    // gzip --start
    const CompressionWebpackPlugin = require('compression-webpack-plugin')
    const productionGzip = true // 是否使用gzip
    const productionGzipExtensions = ['js', 'css'] // 需要gzip压缩的文件后缀
    // gzip --end
    
    const UglifyJsPlugin = require('uglifyjs-webpack-plugin') // 去掉注释
    
    function resolve (dir) {
      return path.join(__dirname, './', dir)
    }
    
    // cdn预加载使用
    const externals = {
      'vue': 'Vue',
      'vue-router': 'VueRouter',
      'vuex': 'Vuex',
      'axios': 'axios',
      'element-ui': 'ELEMENT',
      'js-cookie': 'Cookies',
      'nprogress': 'NProgress'
    }
    
    const cdn = {
      // 开发环境
      dev: {
        css: [
          'https://unpkg.com/element-ui/lib/theme-chalk/index.css',
          'https://cdn.bootcss.com/nprogress/0.2.0/nprogress.min.css'
        ],
        js: []
      },
      // 生产环境
      build: {
        css: [
          'https://unpkg.com/element-ui/lib/theme-chalk/index.css',
          'https://cdn.bootcss.com/nprogress/0.2.0/nprogress.min.css'
        ],
        js: [
          'https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.min.js',
          'https://cdn.jsdelivr.net/npm/vue-router@3.0.1/dist/vue-router.min.js',
          'https://cdn.jsdelivr.net/npm/vuex@3.0.1/dist/vuex.min.js',
          'https://cdn.jsdelivr.net/npm/axios@0.18.0/dist/axios.min.js',
          'https://unpkg.com/element-ui/lib/index.js',
          'https://cdn.bootcss.com/js-cookie/2.2.0/js.cookie.min.js',
          'https://cdn.bootcss.com/nprogress/0.2.0/nprogress.min.js'
        ]
      }
    }
    const cdnDomian = 'http://ppqqg4jtj.bkt.clouddn.com' //静态文件cdn
    
    module.exports = {
      // baseUrl: IS_PROD ? process.env.VUE_APP_SRC || '/' : './', // 默认'/',部署应用包时的基本 URL
      publicPath: IS_PROD ? cdnDomian: '/', // 默认'/',部署应用包时的基本 URL
      outputDir: 'dist',
      assetsDir: '', // 相对于outputDir的静态资源(js、css、img、fonts)目录
      runtimeCompiler: true, // 是否使用包含运行时编译器的 Vue 构建版本
      productionSourceMap: false, // 生产环境的 source map
    
      
      configureWebpack: config => {
      
    
        const myConfig = {}
        if (process.env.NODE_ENV === 'production') {
          // 1. 生产环境npm包转CDN
          myConfig.externals = externals
    
          myConfig.plugins = []
          // gzip
          // 2. 构建时开启gzip,降低服务器压缩对CPU资源的占用,服务器也要相应开启gzip
          productionGzip && myConfig.plugins.push(
            new CompressionWebpackPlugin({
              test: new RegExp('\\.(' + productionGzipExtensions.join('|') + ')$'),
              threshold: 8192,
              minRatio: 0.8
            })
          )
              // 去掉注释
              myConfig.plugins.push(
                new UglifyJsPlugin({
                  uglifyOptions: {
                    output: {
                      comments: false, // 去掉注释
                    },
                    compress: {
                      warnings: false,
                      drop_console: true,
                      drop_debugger: false,
                      pure_funcs: ['console.log']//移除console
                  }
                  }
                })
              )
          
        }
    
        if (process.env.NODE_ENV === 'development') {
          /**
           * 关闭host check,方便使用ngrok之类的内网转发工具
           */
          myConfig.devServer = {
            disableHostCheck: true
          }
        }
    
        return myConfig
      },
    
      chainWebpack: config => {
        // 压缩图片
        config.module
          .rule('images')
          .use('image-webpack-loader')
          .loader('image-webpack-loader')
          .options({
            mozjpeg: { progressive: true, quality: 65 },
            optipng: { enabled: false },
            pngquant: { quality: '65-90', speed: 4 },
            gifsicle: { interlaced: false },
            webp: { quality: 75 }
          })
    
        // 使用cdn
          config.plugin('html').tap(args => {
            if (process.env.NODE_ENV === 'production') {
              args[0].cdn = cdn.build
            }
            if (process.env.NODE_ENV === 'development') {
              args[0].cdn = cdn.dev
            }
            return args
          })
    
        // 打包分析
        if (process.env.IS_ANALYZ) {
          config.plugin('webpack-report').use(BundleAnalyzerPlugin, [
            {
              analyzerMode: 'static'
            }
          ])
        }
        // svg loader
        const svgRule = config.module.rule('svg') // 找到svg-loader
        svgRule.uses.clear() // 清除已有的loader, 如果不这样做会添加在此loader之后
        svgRule.exclude.add(/node_modules/) // 正则匹配排除node_modules目录
        svgRule // 添加svg新的loader处理
          .test(/\.svg$/)
          .use('svg-sprite-loader')
          .loader('svg-sprite-loader')
          .options({
            symbolId: 'icon-[name]'
          })
    
        // 修改images loader 添加svg处理
        const imagesRule = config.module.rule('images')
        imagesRule.exclude.add(resolve('src/icons'))
        config.module
          .rule('images')
          .test(/\.(png|jpe?g|gif|svg)(\?.*)?$/)
      },
      devServer: {
        open: true, // 自动启动浏览器
        host: '0.0.0.0', // localhost
        port: 6060, // 端口号
        https: false,
        hotOnly: false, // 热更新
        proxy: {
          // 本地代理包含user的接口 如: /user/getUser 
          '^/user': {
            target: process.env.VUE_APP_SRC,
            ws: true,   //开启WebSocket
            changeOrigin: true
          },
          '^/v1': {  //匹配包含 /v1的接口  如:v1/xxx/xx
            target: process.env.VUE_APP_V,
            ws: true,
            changeOrigin: true
          }
    
        }
      },
    
    // devServer: {
    //   port: 8080,
    //   before(app) {
    //     app.get('/api/index', (req, res) => {
    //       res.json(mockIndexData)
    //     })
    //   }
    // }
    }
    
    

    完!!

    相关文章

      网友评论

        本文标题:vue-cli3 之vue.config.js配置

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