vue2下vue.config.js+cdn

1,269 阅读1分钟

cdn方式引用包

  • 在入口文件引入第三方cdn资源(无需再通过npm i 方式下载,如element-ui vue-router axios vuex等)
<!DOCTYPE html>
<html lang="">

<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><%= htmlWebpackPlugin.options.title %></title>
  <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
  <script src="https://cdn.staticfile.org/vue/2.6.11/vue.min.js"></script>
  <script src="https://cdn.staticfile.org/axios/0.24.0/axios.min.js"></script>
  <script src="https://cdn.staticfile.org/vue-router/3.5.3/vue-router.min.js"></script>
  <script src="https://cdn.staticfile.org/vuex/3.6.2/vuex.min.js"></script>
  <!-- 引入 element 组件库 -->
  <script src="https://unpkg.com/element-ui/lib/index.js"></script>
</head>

<body>
  <noscript>
    <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled.
      Please enable it to continue.</strong>
  </noscript>
  <div id="app"></div>
  <!-- built files will be auto injected -->
</body>

</html>
  • 根目录下新建vue.config.js
module.exports = {
  // 主要部分
  configureWebpack: {
    externals: {
      'vue': 'Vue',
      'vue-router': 'VueRouter',
      'axios': 'axios',
      'vuex': 'Vuex',
      'element-ui@': 'ELEMENT'
    }
  }
}
  • 使用(就和平常 npm i后的使用一样)
// main.js
import Vue from 'vue'
import App from './App.vue'

// element-ui@取的是vue.config.js文件里externals的键名
import ElementUI from 'element-ui@';
Vue.use(ElementUI);

Vue.config.productionTip = false

new Vue({
  render: h => h(App),
}).$mount('#app')

vue-cli3下vue.config.js常用配置

module.exports = {
  productionSourceMap: false, // true:方便产线排成定位问题,设置true缺点:不过打包后的项目体积大了不少
  publicPath: process.env.NODE_ENV === 'production' ? '/dist' : '/', //静态资源访问路径
  // 输出文件目录
  outputDir: 'dist',
  // eslint-loader 是否在保存的时候检查
  lintOnSave: false,
  // 多页面配置 index键名表示入口页
  pages: {
    login: {
      entry: 'src/login/main.js',
      template: 'public/login.html'
    },
    index: {
      entry: 'src/index/main.js',
      template: 'public/index.html'
    }
  },
  configureWebpack: {
    /**
     * index.html入口页面cdn方式引入包
     * <script src="https://cdn.bootcdn.net/ajax/libs/echarts/5.3.3/echarts.common.min.js"></script>
     * 额外配置  'echarts': 'echarts'
     * 使用  import * as echarts from 'echarts';
     */
    externals: {
      'echarts': 'echarts'
    },
  },
  devServer: {
    host: '0.0.0.0', // 这样设置后,同一个局域网下同事就可以通过你的ip访问你的项目了
    port: 8081, // 本地服务启动后的访问端口号
    proxy: {
      '/api': {
        target: "api-url",   // 实际跨域请求的API地址
        secure: false,   // https请求则使用true
        ws: true, // 允许websocket
        changeOrigin: true,  // 跨域
        // 请求地址重写 由于实际的后端路径不带/api,所以就需要添加下行配置
        pathRewrite: {
          '^/api': '/',
        }
      }
    }
  }
}

vue2下vue.config.js常用生产环境优化性能配置

  • 步骤1.vue.config.js
const path = require('path');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin') // 去掉注释
const CompressionWebpackPlugin = require('compression-webpack-plugin'); // 开启压缩
const { HashedModuleIdsPlugin } = require('webpack');

function resolve (dir) {
  return path.join(__dirname, dir)
}

// const isProduction = process.env.NODE_ENV === 'production';
// 开发环境调试
const isProduction = true

//使用CDN 加速优化
const externals = {
  'vue': 'Vue',
  'vue-router': 'VueRouter',
  'vuex': 'Vuex',
  'axios': 'axios',
  "element-ui": "ELEMENT"
}
const cdnResource = {
  css: [
    'https://unpkg.com/element-ui/lib/theme-chalk/index.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'
  ]
}

module.exports = {
  lintOnSave: false, // 关闭eslint
  productionSourceMap: false, //去除生产环境sourceMap
  publicPath: './',
  outputDir: process.env.outputDir, // 生成文件的目录名称
  chainWebpack: config => {
    config.resolve.alias
      .set('@', resolve('src'))

    // 压缩图片
    config.module
      .rule('images')
      .test(/\.(png|jpe?g|gif|svg)(\?.*)?$/)
      .use('image-webpack-loader')
      .loader('image-webpack-loader')
      .options({ bypassOnDebug: true })

    // webpack 会默认给commonChunk打进chunk-vendors,所以需要对webpack的配置进行delete
    config.optimization.delete('splitChunks')
    config.plugin('html').tap(args => {
      args[0].cdn = cdnResource
      return args
    })

    config
      .plugin('webpack-bundle-analyzer')
      .use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin)
  },

  configureWebpack: config => {
    const plugins = [];

    if (isProduction) {
      plugins.push(
        new UglifyJsPlugin({
          uglifyOptions: {
            output: {
              comments: false, // 去掉注释
            },
            warnings: false,
            compress: {
              drop_console: true,
              drop_debugger: false,
              pure_funcs: ['console.log']//移除console
            }
          }
        })
      )
      // 服务器也要相应开启gzip
      plugins.push(
        new CompressionWebpackPlugin({
          algorithm: 'gzip',
          test: /\.(js|css)$/,// 匹配文件名
          threshold: 10000, // 对超过10k的数据压缩
          deleteOriginalAssets: false, // 不删除源文件
          minRatio: 0.8 // 压缩比
        })
      )

      // 用于根据模块的相对路径生成 hash 作为模块 id, 一般用于生产环境
      plugins.push(
        new HashedModuleIdsPlugin()
      )

      // 开启分离js
      config.optimization = {
        runtimeChunk: 'single',
        splitChunks: {
          chunks: 'all',
          maxInitialRequests: Infinity,
          minSize: 1000 * 60,
          cacheGroups: {
            vendor: {
              test: /[\\/]node_modules[\\/]/,
              name (module) {
                // 排除node_modules 然后吧 @ 替换为空 ,考虑到服务器的兼容
                const packageName = module.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1]
                return `npm.${packageName.replace('@', '')}`
              }
            }
          }
        }
      };

      // 取消webpack警告的性能提示
      config.performance = {
        hints: 'warning',
        //入口起点的最大体积
        maxEntrypointSize: 1000 * 500,
        //生成文件的最大体积
        maxAssetSize: 1000 * 1000,
        //只给出 js 文件的性能提示
        assetFilter: function (assetFilename) {
          return assetFilename.endsWith('.js');
        }
      }

      // 打包时npm包转CDN
      config.externals = externals;
    }

    return { plugins }
  },

  // pluginOptions: {
  //   // 配置全局less
  //   'style-resources-loader': {
  //     preProcessor: 'less',
  //     patterns: [resolve('./src/style/theme.less')]
  //   }
  // },
  devServer: {
    host: '0.0.0.0', // 这样设置后, 同一个局域网下同事就可以通过你的ip访问你的项目了
    port: 8081, // 前端项目编译后使用的端口号,跟webpack配置的port同理
    //配置proxy跨域
    proxy: {
      '/api': {
        target: "api-url",   // 实际跨域请求的API地址
        secure: false,   // https请求则使用true
        ws: true, // 允许websocket
        changeOrigin: true,  // 跨域
        // 请求地址重写  由于真实后端路径不带/api,所以需要添加下行配置
        pathRewrite: {
          '^/api': '/',
        }
      }
    }
  }
}
  • 步骤2.index.html
<!DOCTYPE html>
<html lang="">

<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><%= htmlWebpackPlugin.options.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文件,配置在vue.config.js下 -->
  <% for (var i in
            htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.js) { %>
  <script src="<%= htmlWebpackPlugin.options.cdn.js[i] %>"></script>
  <% } %>
</head>

<body>
  <noscript>
    <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled.
      Please enable it to continue.</strong>
  </noscript>
  <div id="app"></div>
  <!-- built files will be auto injected -->
</body>

</html>
  • 步骤3.package.json注意插件对应的版本,版本问题也会导致编译失败
{
  "name": "vue2x",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint"
  },
  "dependencies": {
    "core-js": "^3.6.5",
    "vue": "^2.6.11"
  },
  "devDependencies": {
    "@vue/cli-plugin-babel": "~4.5.19",
    "@vue/cli-plugin-eslint": "~4.5.19",
    "@vue/cli-service": "~4.5.19",
    "babel-eslint": "^10.1.0",
    "compression-webpack-plugin": "^6.1.1",
    "eslint": "^6.7.2",
    "eslint-plugin-vue": "^6.2.2",
    "uglifyjs-webpack-plugin": "^2.2.0",
    "vue-template-compiler": "^2.6.11",
    "webpack": "^4.46.0"
  },
  "eslintConfig": {
    "root": true,
    "env": {
      "node": true
    },
    "extends": [
      "plugin:vue/essential",
      "eslint:recommended"
    ],
    "parserOptions": {
      "parser": "babel-eslint"
    },
    "rules": {}
  },
  "browserslist": [
    "> 1%",
    "last 2 versions",
    "not dead"
  ]
}

  • 步骤4.使用
// main.js
import Vue from 'vue'
import App from './App.vue'
import ElementUI from 'element-ui';
Vue.use(ElementUI);

Vue.config.productionTip = false
console.log('main.js log')
new Vue({
  render: h => h(App),
}).$mount('#app')

// App.vue
template>
  <div id="app">
    <el-button type="primary">主要按钮</el-button>
  </div>
</template>
  • 步骤5.经build后测试发现一切正常