# 一、模式和环境变量

# 1、环境变量

  我们可以使用process.env来获取当前系统中定义的所有环境变量。

常见的有:process.env.NODE_ENV、process.env.BASE_URL

NODE_ENV 当前应用程序所处的环境 如 development、production 等。
BASE_URL 生产环境时所在的 URL 的基础路径 在 Vue CLI 2 中,BASE_URL 的默认值是 /,在 Vue CLI 3 中,BASE_URL 的默认值是根据 vue.config.js 文件中的 publicPath 选项自动生成的。
VUE_APP_* Vue CLI 中的自定义环境变量 在应用程序中可以使用 process.env.VUE_APP_*来访问这些变量

| PUBLIC_URL | 静态资源(如图片、字体等)的基础 URL | Create React App 项目中的一个环境变量 |

  那上面的这些环境变量有什么应用场景吗(后面会讲到的)?

# 2、publicPath 值

  在 Vue CLI 生成的项目中,如果设置了 publicPath 选项,那么在应用中,可以使用 process.env.BASE_URL 代替 vue router@3 中的 base 选项的值。

// vue router@3中
const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

// 静态资源中
<img src="${process.env.BASE_URL}/assets/logo.png" />

  并且我们在设置 publicPath 选项时,还可以使用process.env.NODE_ENV来区分生产环境

publicPath 存在的意义

  publicPath 并不是必填项。但当我们的应用程序部署到一个非域名根路径的子路径上时,默认的 绝对路径'/'会导致项目的路由、静态资源找不到。

module.exports = defineConfig({
  // publicPath: '/'
  // publicPath: process.env.NODE_ENV === 'production' ? '/my-app/' : '/' // 绝对路径
  publicPath: process.env.NODE_ENV === 'production' ? './' : '/' // 相对路径 👏
})

# 3、配置文件

  除此之外,我们还可以创建像.env.[NODE_ENV] 类似的文件用于存放不同环境下的环境变量

  • .env

开发、生产环境都可以用

VUE_APP_NAME = 'lencamo'
  • .env.production

生产环境可用

生产环境中的 VUE_APP_BASE_API 为什么不用加 ip 地址

  生产环境下的 VUE_APP_BASE_API 仅仅是一个后端接口标识,Nginx 会利用该标识代理到真正的后端接口地址 https://api.example.com/api

# just a flag
ENV = 'production'

# base api
VUE_APP_BASE_API = /prod-api
应用 1:axios 请求基地址 baseURL
  • 环境配置
# .env.development
VUE_APP_BASE_API = /api # 使用项目自身 webpack-dev-serve 的Mock接口
VUE_APP_BASE_API = http://localhost:3000/api # 使用本地后端接口
VUE_APP_BASE_API = https://api.example.com/api # 使用服务器线上接口

# .env.production
VUE_APP_BASE_API = /prod-api # 后端接口标识
  • axios 实例
import axios from 'axios'

// 以前
// let BASE_URL = ''
// if (process.env.NODE_ENV === 'production') {
//   BASE_URL = 'http://localhost:8080/api'
// } else {
//   BASE_RUL = 'http://localhost:8080/api'
// }

// const request = axios.create({
//   baseURL: BASE_URL
//   // ……
// })

// 现在
const request = axios.create({
  baseURL: process.env.VUE_APP_BASE_API
  // ……
})
应用 2:devServer 的运行端口 port
// port = 9527 npm run dev OR npm run dev --port = 9527
const port = process.env.port || process.env.npm_config_port || 9527 // dev port

medule.exports = {
  devServer: {
    port: prot
  }
}

# 二、性能优化 ✨

  通过npm run serve运行项目发现其效果类似于 webpack 中的 webpack-dev-server 辅助插件。

{
"scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build"
  },
}

注意:

  之前使用 webpack 时,开发环境中打包使用的是dev脚本而不是serve脚本

性能优化汇总
const TerserPlugin = require('terser-webpack-plugin')
const CompressionWebpackPlugin = require('compression-webpack-plugin')

module.exports = defineConfig({
  // dist预览
  publicPath: process.env.NODE_ENV === 'development' ? '/' : './',

  // 关闭SourceMap
  productionSourceMap: false,

  chainWebpack: (config) => {
    config.when(process.env.NODE_ENV !== 'development', (config) => {
      // 图片处理
      config.module
        .rule('images')
        .use('url-loader')
        .loader('url-loader')
        .tap((options) => {
          options.limit = 10 & 1024
          return options
        })

      // 调试代码处理
      config.optimization.minimizer('terser').tap((args) => {
        args[0].parallel = 4
        args[0].terserOptions = {
          compress: {
            warnings: true,
            drop_console: true,
            drop_debugger: true
          }
        }
        return args
      })

      // 打包压缩
      config.plugins.push(
        new CompressionWebpackPlugin({
          filename: '[path].gz[query]',
          algorithm: 'gzip',
          test: /\.(js|css)$/,
          threshold: 10240,
          deleteOriginalAssets: false
          // minRatio: 0.8
        })
      )
    })
  }
})

# 1、dist 预览

  dist 文件项目预览:

不使用 publicPath, 打包的项目必须保证 dist 的内容在服务器的根目录

  • vue.config.js
module.exports = defineConfig({
  publicPath: process.env.NODE_ENV === 'development' ? '/' : './'
})

# 2、路由懒加载

# 3、组件库按需引入

  下面摘取几个常用的组件库看看:

# ① element ui

完整引入
  • main.js
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'

Vue.use(ElementUI)
按需引入(手动)✨

先安装:

npm install babel-plugin-component -D

然后配置:

  • .babelrc
// 版本 <= CLI2x时
{
  "presets": [["es2015", { "modules": false }]],
  "plugins": [
    [
      "component",
      {
        "libraryName": "element-ui",
        "styleLibraryName": "theme-chalk"
      }
    ]
  ]
}
  • babel.config.js
// 版本 <= CLI2x时
module.exports = {
  presets: ['@vue/cli-plugin-babel/preset'],
  plugins: [
    [
      'component',
      {
        libraryName: 'element-ui',
        styleLibraryName: 'theme-chalk'
      }
    ]
  ]
}

最后使用:

通常情况下,按需引入的文件可以单独提取出来,方便管理

  • main.js
import './plugins/element.js'
  • plugins / element.js
import { Button, Select } from 'element-ui'
Vue.use(Button)
Vue.use(Select)
按需引入(自动)

参考:https://juejin.cn/post/6968448909769179172

vue add element

  建议还是使用上面的手动方式,原因如下:

  • 安装时,它会更新项目入口文件 App.vue
  • 卸载时,不容易成功

# ② vant

# 4、关闭 SourceMap

module.exports = defineConfig({
  productionSourceMap: false
})

# 5、图片处理

module.exports = defineConfig({
  chainWebpack: (config) => {
    config.module
      .rule('images')
      .use('url-loader')
      .loader('url-loader')
      .tap((options) => Object.assign(options, { limit: 10 * 1024 })) // 10 kb 以下转换为base64
  }
})

# 6、CDN 链接 ✍

  我们可以通过 CDN 减小包体积,达到性能优化的目的。

更多的 vue-cli 配置可以参考:https://cli.vuejs.org/zh/config/

简单实现
  • vue.config.js
const path = require('path')

module.exports = {
  configureWebpack: {
    // 不需要打包的包
    externals: {
      qc: 'QC'
    }
  }
}
  • public / index.html
<body>
  <!-- built files will be auto injected -->
  <!-- 手动引入QC模块 -->
  <script
    src="http://connect.qq.com/qc_jssdk.js"
    data-appid="100556005"
    data-redirecturi="http://www.corho.com:8080/#/login/callback"
  ></script>
</body>

  推荐一个免费的 CDN 网站:https://unpkg.com/

unpkg.com/:package@:version/:file
  • vue.config.js
代码实现
// 不使用npm安装的包
let externals = {}
// 要使用的第三方CDN包链接
let CDN = { css: [], js: [] }

// 正式配置
if (process.env.NODE_ENV === 'production') {
  externals = {
    // 基本格式:
    // '包名' : '在项目中引入的名字'
    vue: 'Vue',
    'vue-router': 'VueRouter',
    vuex: 'Vuex',
    axios: 'axios',
    'element-ui': 'ELEMENT' // cdn里的源代码配置💖在ELEMENT这个变量
    // (一定要去修改掉引入Element用的变量名, 这里要匹配ELEMENT去替换)
    // ……
  }
  CDN = {
    css: [
      'https://unpkg.com/[email protected]/lib/theme-chalk/index.css'
      // ……
    ],
    js: [
      // vue must at first!
      'https://unpkg.com/[email protected]/dist/vue.js',
      'https://unpkg.com/[email protected]/dist/vue-router.js',
      'https://unpkg.com/[email protected]/dist/vuex.js',
      'https://unpkg.com/[email protected]/dist/axios.min.js',
      'https://unpkg.com/[email protected]/lib/index.js'
      // ……
    ]
  }
}

module.exports = defineConfig({
  // 需要排除的包对象
  configureWebpack: {
    externals: externals
  },

  // 方式1
  // 修改原webpack配置(https://webpack.js.org/plugins/html-webpack-plugin/)
  chainWebpack: (config) => {
    // vue-cli中修改html-webpack-plugin插件(https://cli.vuejs.org/zh/guide/webpack.html#%E4%BF%AE%E6%94%B9%E6%8F%92%E4%BB%B6%E9%80%89%E9%A1%B9)
    config.plugin('html').tap((args) => {
      args[0].cdn = CDN // 添加新参数
      return args
    })
  },
  // 方式2
  // 使用vue-cli的page配置(https://cli.vuejs.org/zh/config/#pages)
  pages: {
    index: {
      cdn: CDN // 添加新参数
    }
  }
})
  • public/index.html
代码实现
<head>
  <!-- 1、引入CDN的css链接 -->
  <% for(var css of htmlWebpackPlugin.options.cdn.css) { %>
  <link rel="stylesheet" href="<%=css%>" />
  <% } %>
  <!-- …… -->
</head>
<body>
  <!-- 2、引入CDN的js链接 -->
  <!-- built files will be auto injected -->
  <% for(var js of htmlWebpackPlugin.options.cdn.js) { %>
  <script src="<%=js%>"></script>
  <% } %>
  <!-- …… -->
</body>

# 7、清除注释/调试代码

  先安装:

npm install terser-webpack-plugin -D

  然后在 vue.config.js 中进行配置:

const TerserPlugin = require('terser-webpack-plugin') // 去除console.log和debugger语句

module.exports = {
  chainWebpack(config) {
    config.optimization.minimizer('terser').tap((args) => {
      args[0].parallel = 4
      args[0].terserOptions = {
        compress: {
          warnings: true,
          drop_console: true, // 删除debugger
          drop_debugger: true // 删除console
        }
      }
      return args
    })
  }
}

# 8、gzip 压缩

提示

  当然我们也可以考虑使用服务器端的压缩技术来优化性能,比如 Nginx 服务器可以使用 gzip 压缩技术。

  先安装:

npm install compression-webpack-plugin -D

  然后在 vue.config.js 中进行配置:

const CompressionWebpackPlugin = require('compression-webpack-plugin') // 开启压缩

module.exports = {
  configureWebpack: (config) => {
    // 查看打包文件体积大小
    config.plugins.push(
      new CompressionWebpackPlugin({
        filename: '[path].gz[query]',
        algorithm: 'gzip',
        test: /\.(js|css)$/, // 匹配需要压缩的文件
        threshold: 10240, // 对超过10kb的数据压缩
        deleteOriginalAssets: false // 是否删除原文件
        // minRatio: 0.8 // 压缩比
      })
    )
  }
}
更新于 : 8/7/2024, 2:16:31 PM