vue create

? Check the features needed for your project: (Press to select, to toggle all, to invert selection)
>( ) Babel //转码器,可以将ES6代码转为ES5代码,从而在现有环境执行。
( ) TypeScript// TypeScript是一个JavaScript(后缀.js)的超集(后缀.ts)包含并扩展了 JavaScript 的语法,需要被编译输出为 JavaScript在浏览器运行
( ) Progressive Web App (PWA) Support// 渐进式Web应用程序
( ) Router // vue-router(vue路由)
( ) Vuex // vuex(vue的状态管理模式)
( ) CSS Pre-processors // CSS 预处理器(如:less、sass)
( ) Linter / Formatter // 代码风格检查和格式化(如:ESlint)
( ) Unit Testing // 单元测试(unit tests)
( ) E2E Testing // e2e(end to end) 测试

vue.config.js

  1. const path = require('path');
  2. const IS_PROD = ['production', 'prod'].includes(process.env.NODE_ENV);
  3. const resolve = (dir) => path.join(__dirname, dir);
  4. console.log('NODE_ENV===', process.env.NODE_ENV);
  5. console.log('IS_PROD===', IS_PROD);
  6. module.exports = {
  7. publicPath: IS_PROD ? './' : '/', // 公共路径
  8. indexPath: 'index.html', // 相对于打包路径index.html的路径
  9. outputDir: process.env.outputDir || 'dist', // 'dist', 生产环境构建文件的目录
  10. assetsDir: 'static', // 相对于outputDir的静态资源(js、css、img、fonts)目录
  11. lintOnSave: true, // 是否在开发环境下通过 eslint-loader 在每次保存时 lint 代码
  12. // runtimeCompiler: true, // 是否使用包含运行时编译器的 Vue 构建版本
  13. productionSourceMap: !IS_PROD, // 生产环境的 source map
  14. parallel: require("os").cpus().length > 1, // 是否为 Babel 或 TypeScript 使用 thread-loader。该选项在系统的 CPU 有多于一个内核时自动启用,仅作用于生产构建。
  15. pwa: {}, // 向 PWA 插件传递选项。
  16. chainWebpack: config => {
  17. config.plugin('html')
  18. .tap(args => {
  19. args[0].title = 'H5前端框架'
  20. return args
  21. })
  22. config.optimization
  23. .runtimeChunk(true)
  24. // 引入less全局变量
  25. const oneOfsMap = config.module.rule('less').oneOfs.store
  26. oneOfsMap.forEach(item => {
  27. item
  28. .use('sass-resources-loader')
  29. .loader('sass-resources-loader')
  30. .options({
  31. resources: [
  32. path.resolve(__dirname, './src/assets/less/base.less'), // 不采用此移动端适配方案
  33. path.resolve(__dirname, './src/assets/less/public.less')
  34. ]
  35. })
  36. .end()
  37. })
  38. config.resolve.symlinks(true); // 修复热更新失效
  39. // 如果使用多页面打包,使用vue inspect --plugins查看html是否在结果数组中
  40. config.plugin("html").tap(args => {
  41. // 修复 Lazy loading routes Error
  42. args[0].chunksSortMode = "none";
  43. return args;
  44. });
  45. config.resolve.alias // 添加别名
  46. .set('@', resolve('src'))
  47. .set('@assets', resolve('src/assets'))
  48. .set('@components', resolve('src/components'))
  49. .set('@baseComponents', resolve('src/base-components'))
  50. .set('@utils', resolve('src/libs/utils'))
  51. .set('@views', resolve('src/views'))
  52. .set('@store', resolve('src/store'));
  53. },
  54. css: {
  55. extract: IS_PROD,
  56. requireModuleExtension: true,// 去掉文件名中的 .module
  57. loaderOptions: {
  58. // 给 less-loader 传递 Less.js 相关选项
  59. less: {
  60. // `globalVars` 定义全局对象,可加入全局变量 eg: color: @primary;
  61. globalVars: {
  62. // primary: 'red'
  63. }
  64. }
  65. }
  66. },
  67. devServer: {
  68. overlay: { // 让浏览器 overlay 同时显示警告和错误
  69. warnings: true,
  70. errors: true
  71. },
  72. host: "0.0.0.0",
  73. port: 8080, // 端口号
  74. https: false, // https:{type:Boolean}
  75. open: true, //配置自动启动浏览器
  76. hotOnly: true, // 热更新
  77. // proxy: 'http://localhost:8080' // 配置跨域处理,只有一个代理
  78. proxy: { //配置多个跨域
  79. "/h5api": {
  80. target: "http://172.11.11.11:7071",
  81. changeOrigin: true,
  82. // ws: true,//websocket支持
  83. secure: false,
  84. pathRewrite: {
  85. "^/h5api": ""
  86. },
  87. logLevel: 'debug', // 查看代理日志
  88. },
  89. "/api2": {
  90. target: "http://172.12.12.12:2018",
  91. changeOrigin: true,
  92. //ws: true,//websocket支持
  93. secure: false,
  94. pathRewrite: {
  95. "^/api2": "/"
  96. },
  97. logLevel: 'debug',
  98. },
  99. }
  100. }
  101. }

完整配置

  1. 'use strict'
  2. const path = require('path')
  3. function resolve(dir) {
  4. return path.join(__dirname, dir)
  5. }
  6. const CompressionPlugin = require('compression-webpack-plugin')
  7. const name = process.env.VUE_APP_TITLE || '三体' // 网页标题
  8. const port = process.env.port || process.env.npm_config_port || 80 // 端口
  9. // vue.config.js 配置说明
  10. //官方vue.config.js 参考文档 https://cli.vuejs.org/zh/config/#css-loaderoptions
  11. // 这里只列一部分,具体配置参考文档
  12. module.exports = {
  13. // 部署生产环境和开发环境下的URL。
  14. // 默认情况下,Vue CLI 会假设你的应用是被部署在一个域名的根路径上
  15. // 例如 https://www.ruoyi.vip/。如果应用被部署在一个子路径上,你就需要用这个选项指定这个子路径。例如,如果你的应用被部署在 https://www.ruoyi.vip/admin/,则设置 baseUrl 为 /admin/。
  16. // 部署多个项目,用文件夹区分
  17. publicPath: process.env.NODE_ENV === "production" ? "/" : "/",
  18. // 在npm run build 或 yarn build 时 ,生成文件的目录名称(要和baseUrl的生产环境路径一致)(默认dist)
  19. outputDir: 'dist',
  20. // 用于放置生成的静态资源 (js、css、img、fonts) 的;(项目打包之后,静态资源会放在这个文件夹下)
  21. assetsDir: 'static',
  22. // 是否开启eslint保存检测,有效值:ture | false | 'error'
  23. lintOnSave: process.env.NODE_ENV === 'development',
  24. // 如果你不需要生产环境的 source map,可以将其设置为 false 以加速生产环境构建。
  25. productionSourceMap: false,
  26. // webpack-dev-server 相关配置
  27. devServer: {
  28. host: '0.0.0.0',
  29. port: port,
  30. open: true,
  31. proxy: {
  32. // detail: https://cli.vuejs.org/config/#devserver-proxy
  33. [process.env.VUE_APP_BASE_API]: {
  34. target: `http://localhost:8080`,
  35. changeOrigin: true,
  36. pathRewrite: {
  37. ['^' + process.env.VUE_APP_BASE_API]: ''
  38. }
  39. }
  40. },
  41. disableHostCheck: true
  42. },
  43. css: {
  44. loaderOptions: {
  45. sass: {
  46. sassOptions: { outputStyle: "expanded" }
  47. }
  48. }
  49. },
  50. configureWebpack: {
  51. name: name,
  52. resolve: {
  53. alias: {
  54. '@': resolve('src')
  55. }
  56. },
  57. plugins: [
  58. // http://doc.ruoyi.vip/ruoyi-vue/other/faq.html#使用gzip解压缩静态文件
  59. new CompressionPlugin({
  60. test: /\.(js|css|html)?$/i, // 压缩文件格式
  61. filename: '[path].gz[query]', // 压缩后的文件名
  62. algorithm: 'gzip', // 使用gzip压缩
  63. minRatio: 0.8 // 压缩率小于1才会压缩
  64. })
  65. ],
  66. },
  67. chainWebpack(config) {
  68. config.plugins.delete('preload') // TODO: need test
  69. config.plugins.delete('prefetch') // TODO: need test
  70. // set svg-sprite-loader
  71. config.module
  72. .rule('svg')
  73. .exclude.add(resolve('src/assets/icons'))
  74. .end()
  75. config.module
  76. .rule('icons')
  77. .test(/\.svg$/)
  78. .include.add(resolve('src/assets/icons'))
  79. .end()
  80. .use('svg-sprite-loader')
  81. .loader('svg-sprite-loader')
  82. .options({
  83. symbolId: 'icon-[name]'
  84. })
  85. .end()
  86. config
  87. .when(process.env.NODE_ENV !== 'development',
  88. config => {
  89. config
  90. .plugin('ScriptExtHtmlWebpackPlugin')
  91. .after('html')
  92. .use('script-ext-html-webpack-plugin', [{
  93. // `runtime` must same as runtimeChunk name. default is `runtime`
  94. inline: /runtime\..*\.js$/
  95. }])
  96. .end()
  97. config
  98. .optimization.splitChunks({
  99. chunks: 'all',
  100. cacheGroups: {
  101. libs: {
  102. name: 'chunk-libs',
  103. test: /[\\/]node_modules[\\/]/,
  104. priority: 10,
  105. chunks: 'initial' // only package third parties that are initially dependent
  106. },
  107. elementUI: {
  108. name: 'chunk-elementUI', // split elementUI into a single package
  109. priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app
  110. test: /[\\/]node_modules[\\/]_?element-ui(.*)/ // in order to adapt to cnpm
  111. },
  112. commons: {
  113. name: 'chunk-commons',
  114. test: resolve('src/components'), // can customize your rules
  115. minChunks: 3, // minimum common number
  116. priority: 5,
  117. reuseExistingChunk: true
  118. }
  119. }
  120. })
  121. config.optimization.runtimeChunk('single'),
  122. {
  123. from: path.resolve(__dirname, './public/robots.txt'), //防爬虫文件
  124. to: './' //到根目录下
  125. }
  126. }
  127. )
  128. }
  129. }

compression-webpack-plugin

vuecli使用注意事项: https://segmentfault.com/a/1190000040268844

vue TypeError: Cannot read property ‘tapPromise‘ of undefined

原因: compression-webpack-plugin”这个版本高了
解决:

  1. // 卸载
  2. npm uninstall compression-webpack-plugin
  3. // 安装
  4. npm i -D compression-webpack-plugin@6.1.1
  1. # 配置
  2. const CompressionPlugin = require('compression-webpack-plugin')
  3. configureWebpack: (config) => {
  4. if (process.env.NODE_ENV === 'production') {
  5. // 为生产环境修改配置...
  6. config.mode = 'production'
  7. return {
  8. plugins: [new CompressionPlugin({
  9. test: /\.js$|\.html$|\.css/, //匹配文件名
  10. threshold: 10240, //对超过10k的数据进行压缩
  11. deleteOriginalAssets: false //是否删除原文件
  12. })]
  13. }
  14. }

Express响应处理

在服务器我们也要做相应的配置 如果发送请求的浏览器支持gzip,就发送给它gzip格式的文件 我的服务器是用express框架搭建的 只要安装一下compression就能使用

  1. const compression = require('compression')
  2. app.use(compression()) // 在其他中间件使用之前调用

Nginx 开启 gzip_static 功能

  1. # 开启和关闭gzip模式
  2. gzip on;
  3. # gizp压缩起点,文件大于1k才进行压缩
  4. gzip_min_length 1k;
  5. # 设置压缩所需要的缓冲区大小,以4k为单位,如果文件为7k则申请2*4k的缓冲区
  6. gzip_buffers 4 16k;
  7. # 设置gzip压缩针对的HTTP协议版本
  8. gzip_http_version 1.1;
  9. # gzip 压缩级别,1-9,数字越大压缩的越好,也越占用CPU时间
  10. gzip_comp_level 2;
  11. # 需要压缩的文件mime类型
  12. gzip_types text/plain application/javascript application/x-javascript text/javascript text/css application/xml;
  13. # 是否在http header中添加Vary: Accept-Encoding,建议开启
  14. gzip_vary on;
  15. # nginx做前端代理时启用该选项,表示无论后端服务器的headers头返回什么信息,都无条件启用压缩
  16. gzip_proxied expired no-cache no-store private auth;
  17. # 不启用压缩的条件,IE6对Gzip不友好,所以不压缩
  18. gzip_disable "MSIE [1-6]\.";
  19. location / {
  20. root D:\mine-project\pc-web\dist;
  21. index index.html index.htm;
  22. try_files $uri $uri/ /index.html;
  23. add_header Cache-Control no-cache;
  24. add_header Content-Encoding gzip;
  25. }

服务端设置响应头: content-encoding=gzip
网页gzip压缩检测: http://tool.chinaz.com/Gzips/

gzip
https://blog.csdn.net/fxss5201/article/details/106535475
关于 nginx 的 gzip ,可以分为两种:

  1. nginx 动态压缩,对每个请求先压缩再输出。gzip on;
  2. nginx 静态压缩,使用现成的扩展名为 .gz 的预压缩文件。gzip_static配置优先级高于gzip。开启nginx_static后,对于任何文件都会先查找是否有对应的gz文件。

另一篇 Nginx优化: https://www.yuque.com/allblue-byynd/lisfg2/cl9b8h

代码压缩

  1. npm i uglifyjs-webpack-plugin -D
  1. // vue.config.js
  2. // 代码压缩
  3. const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
  4. ...
  5. configureWebpack: {
  6. plugins: [
  7. // 生产环境下配置
  8. new UglifyJsPlugin({
  9. uglifyOptions: {
  10. compress: {
  11. drop_debugger: true,
  12. drop_console: true, //生产环境自动删除console
  13. },
  14. warnings: false,
  15. },
  16. cache: false, //是否启用文件缓存,默认缓存在node_modules/.cache/uglifyjs-webpack-plugin.目录
  17. sourceMap: false,
  18. parallel: true // 使用多进程并行运行来提高构建速度。默认并发运行数:os.cpus().length - 1。
  19. })
  20. ]
  21. }
包大小 策略
0 KB 至 10 KB 合并包
10 KB 至 100 KB 大小合适
100 KB 至 200 KB 核心包,重点关注
大于 200 KB 考虑拆包
特殊情况 特殊处理