Skip to content

chenweihuan/vue-cli3-config-reference

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

39 Commits
 
 
 
 
 
 

Repository files navigation

vue-cli3的配置参考

☀️   初衷:关于vue-cli3配置参考,google出来的结果大多不理想。所以自己收集捣鼓总结vue-cli3-config-reference。

👉   vue-cli在2019-11-27发布了新版本v4.1.0,后续会新开vue-cli4的分支,记录总结config-reference。

0️⃣   以下例子均基于@vue/cli v3.11.0

$ vue --version
3.11.0

📑  目录

✅  取消eslint错误显示在浏览器中

运行vue create新建的项目,默认的lintOnSave:'error',lint 错误不仅仅输入到命令行,也直接显示在浏览器中。设置lintOnSave:true即可。

  • true:eslint-loader 会将 lint 错误输出为编译警告。默认情况下,警告仅仅会被输出到命令行,且不会使得编译失败。
  • 'error':这会强制 eslint-loader 将 lint 错误输出为编译错误,同时也意味着 lint 错误将会导致编译失败。
  • false:取消eslint检查。
// vue.config.js
module.exports = {
  lintOnSave: true
}

tip:修改配置重启后,如无效果,需要Ctrl+s保存文件,触发检查。

参考:vue-cli3文档#lintonsave

⬆️:  回到顶部

✅  启用构建速度分析工具

$ yarn add speed-measure-webpack-plugin -D

配置vue.config.js,实例化一下SpeedMeasurePlugin,包住configureWebpack就可以啦。

// vue.config.js
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin")
// 可传options参数,参考https://www.npmjs.com/package/speed-measure-webpack-plugin
const smp = new SpeedMeasurePlugin()

module.exports = {
  configureWebpack: smp.wrap({
    plugins: []
  })
}

跑一下npm run build,效果就出来啦!!!

 SMP  ⏱
General output time took 1 min, 18.38 secs

 SMP  ⏱  Plugins
CompressionPlugin took 0.196 secs

 SMP  ⏱  Loaders
modules with no loaders took 55.73 secs
  module count = 2293
vuetify-loader, and
cache-loader, and
vue-loader, and
eslint-loader took 45.29 secs
  module count = 383
cache-loader, and
thread-loader, and
babel-loader, and
vuetify-loader, and
cache-loader, and
vue-loader took 40.36 secs
...

⬆️:  回到顶部

✅  启用bundle分析工具

$ vue add webpack-bundle-analyzer

不需要配置任何script,在build的时候加上--report即可。在开发环境中,默认自动打开http://127.0.0.1:8888,查看分析报告,由于 webpack-bundle-analyzer 需要物理文件来计算已解析和gzip压缩的大小,因此只能使用stat大小;如果运行npm run build --report,dist目录下会生成report.html,默认自动打开该文件。
关闭自动打开分析文件功能:

// vue.config.js
module.exports = {
  pluginOptions: {
    webpackBundleAnalyzer: {
      openAnalyzer: false
    }
  }
}

参考:vue-cli-plugin-webpack-bundle-analyzer

⬆️:  回到顶部

✅  lodash按需引入

  1. 只安装并引入你需要的lodash包
$ yarn remove lodash
$ yarn add lodash.clonedeep -S
//在需要的地方引入
import cloneDeep from "lodash.clonedeep";
  1. 使用babel-plugin-lodash
$ yarn add babel-plugin-lodash -D

修改.babelrc文件:

{
    "plugin":["lodash"]
}
  1. 使用lodash-es
    webpack的 tree-shaking 只对es6模块生效,而lodash本身是commonjs模块,所以import { cloneDeep } from "lodash"是实现不了按需加载的,但是它有一个lodash-es版本,用的就是es6模块。
$ yarn add lodash-es -S
import { cloneDeep } from 'lodash-es' 
// 相当于 import cloneDeep from "lodash.clonedeep";

⬆️:  回到顶部

✅  moment按需引入语言包

moment支持123种语言,但它又不能事先知道你需要哪一种语言包,保险起见,打包的时候会把所有的语言包打包进去。默认是en,所以en这个语言包是肯定会自动打包进去的。

// 国际化示例
moment.locale('zh-cn')
moment().format('LLL')  // 2019年11月19日早上8点46分

moment.locale('en')
moment().format('LLL')  // November 19, 2019 8:48 AM

webpack-bundle-analyzer分析图如下:

  1. 按需引入语言包
// vue.config.js,下面只引入中国和中国香港的语言包,可根据自身需求引入
const webpack = require('webpack')

module.exports = {
  chainWebpack: config => {
    config
      .plugin('ignore')
      .use(new webpack.ContextReplacementPlugin(/moment[/\\]locale$/, /(zh-cn)|(zh-hk)$/))
    return config
  }
}
  1. 忽略所有语言包,并使用import单独引入特定语言包
// vue.config.js
const webpack = require('webpack');
module.exports = {
  chainWebpack: config => {
    config
      .plugin('ignorePlugin')
      .use(webpack.IgnorePlugin, [{     // 引入的文件路径匹配/^\.\/locale$/,则会忽略这个文件, 也就不会被打包进去
        resourceRegExp: /^\.\/locale$/, // 忽略所有语言包,所有locale功能失效,功能缺失那肯定是不允许的。在main.js单独引入语言包即可
        contextRegExp: /moment$/,
      }]);
  }
}
//main.js
import moment from 'moment'
import 'moment/locale/zh-cn'
moment.locale('zh-cn')
console.log(moment().format('LLL')) // 2019年11月19日早上8点46分
  1. 使用date-fns或dayjs替代
名字 大小(gzip) 支持Tree-shaking api方法数 时区支持 支持语言数
Moment.js 329K(69.6K) No 非常好 123
date-fns 78.4k(13.4k) without tree-shaking YES 还不支持 32
dayjs 6.5k(2.6k) without plugins No 还不支持 23

⬆️:  回到顶部

✅  启用静态压缩

启用压缩分为动态压缩和静态压缩。

  • 动态压缩是由nginx对每个请求进行压缩, 缺点是压缩过程占用cpu的资源,压缩比越高cpu占用越高,不需要修改webpack配置,修改nginx.conf文件即可。
  • 静态压缩:使用compression-webpack-plugin对打包文件进行压缩,会生成对应的.gz文件。nginx发现存在对应的.gz文件后,会使用该压缩文件,就不需要自己压缩一遍了。
yarn add compression-webpack-plugin -D
// vue.config.js
const CompressionPlugin = require('compression-webpack-plugin')
module.exports = {
  configureWebpack: config => {
    if (process.env.NODE_ENV === 'production') {
      config.mode = 'production'
      return {
        plugins: [new CompressionPlugin({
          test: /\.js$|\.html$|\.css/,
          threshold: 10240,//大于10kb的就进行压缩
          deleteOriginalAssets: false //是否删除源文件
        })]
      }
    }
  }
}

配置nginx,在http、server、location下加以下代码:

# 开启静态压缩
gzip_static on; 
#识别http的协议版本。由于早期的一些浏览器或者http客户端,可能不支持gzip自解压,用户就会看到乱码,所以做一些判断还是有必要的
gzip_http_version   1.1; 
# 启用压缩,如果header包含expired no-cache no-store private auth其中一种
gzip_proxied        expired no-cache no-store private auth; 
# 不启用压缩的条件,IE6对Gzip不友好,所以不压缩
gzip_disable        "MSIE [1-6]\."; 
# 和http头有关系,加个vary头,给代理服务器用的,有的浏览器支持压缩,有的不支持,所以避免浪费不支持的也压缩,所以根据客户端的HTTP头来判断,是否需要压缩
gzip_vary  on;

如果使用的是node和express,在需要启用静态压缩的中间件前注册一个中间价即可:

const compression = require('compression')
app.use(compression())

如需启用开发环境的静态压缩,配置devServer即可:

// vue.config.js
module.exports = {
  devServer:{
    compress: true
  }
}

参考:webpack官网 devServer.compress

⬆️:  回到顶部

✅  启用js和css的sourceMap

css.sourceMap

为CSS开启sourceMap后,在检索元素查看css时,可以精确知道来自于哪一个文件,点击文件名,可以到达Sources面板查看该文件。

// vue.config.js
module.exports = {
  css: {
    sourceMap: false
  }
}

参考:vue-cli文档#css-sourcemap

Javascript.sourceMap

生产环境中,vue-cli是默认开启的,为Javascript开启sourceMap后,构建时会生成.map文件,可以帮助你在生产环境调试代码,当然,开启sourceMap后就会影响项目的构建速度。

module.exports = {
  productionSourceMap: false,  // 生产环境禁用
  configureWebpack: {
    devtool: false // 开发环境禁用
  }
}

参考:
配置 js.sourceMap
vue-cli文档#productionsourcemap
更多devtool配置

⬆️:  回到顶部

✅  DllPlugin配置

vue 开发过程中,保存一次就会编译一次。利用DllPlugin,把一些库(一般不会去改动)提取出来,只编译修改的js文件,加快编译的速度。

yarn add webpack-cli@^3.2.3 add-asset-html-webpack-plugin@^3.1.3 clean-webpack-plugin@^3.0.0  -D

在项目根目录下新建 webpack.dll.conf.js:

// webpack.dll.conf.js
const path = require('path')
const webpack = require('webpack')
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

// dll文件存放的目录
const dllPath = 'public/vendor'

module.exports = {
  entry: {
    // 需要提取的库文件
    vendor: ['vue', 'vue-router', 'vuex', 'axios', 'element-ui']
  },
  output: {
    path: path.join(__dirname, dllPath),
    filename: '[name].dll.js',
    // vendor.dll.js中暴露出的全局变量名
    // 保持与 webpack.DllPlugin 中名称一致
    library: '[name]_[hash]'
  },
  plugins: [
    // 清除之前的dll文件
    new CleanWebpackPlugin(),
    // 设置环境变量
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: 'production'
      }
    }),
    // manifest.json 描述动态链接库包含了哪些内容
    new webpack.DllPlugin({
      path: path.join(__dirname, dllPath, '[name]-manifest.json'),
      // 保持与 output.library 中名称一致
      name: '[name]_[hash]',
      context: process.cwd()
    })
  ]
}

生成 dll:添加dll选项,并运行yarn run dll

// package.json
"scripts": {
    "dll": "webpack -p --progress --config ./webpack.dll.conf.js"
},

为了节约编译的时间,这时间我们需要告诉 webpack 公共库文件已经编译好了,减少 webpack 对公共库的编译时间。

// vue.config.js
const path = require('path')
const webpack = require('webpack')
const AddAssetHtmlPlugin = require('add-asset-html-webpack-plugin')

module.exports = {
    ...
    configureWebpack: {
        plugins: [
          new webpack.DllReferencePlugin({
            context: process.cwd(),
            manifest: require('./public/vendor/vendor-manifest.json')
          }),
          // 将 dll 注入到 生成的 html 模板中
          new AddAssetHtmlPlugin({
            filepath: path.resolve(__dirname, './public/vendor/*.js'),// dll文件位置
            publicPath: './vendor',// dll 引用路径
            outputPath: './vendor'// dll最终输出的目录
          })
        ]
    }
}

疑惑:添加DllPlugin后,每次保存后重新编译时间确实减少了,从平均3.6s降到2.4s。但是运行yarn run serve,编译时间几乎一样。后续还得探索探索...

参考:vue-cli3 DllPlugin 提取公用库

⬆️:  回到顶部

✅  添加别名alias

  1. 配置configureWebpack
const path = require('path')
const resolve = dir => path.join(__dirname, dir)

module.exports = {
  configureWebpack: {
    resolve: {
      alias: {
        '@components': resolve('src/components'),
        '@': resolve('src')
      }
    }
  }
}
  1. 配置chainWebpack
const path = require('path')
const resolve = dir => path.join(__dirname, dir)

module.exports = {
  chainWebpack:config => {
    config.resolve.alias
      .set('@components',resolve('src/components'))
      .set('@',resolve('src'))
  }
}

参考:how to set alias

⬆️:  回到顶部

✅  去除console.log

  1. 使用 babel-plugin-transform-remove-console 插件
yarn add babel-plugin-transform-remove-console -D

添加babel配置:

const IS_PROD = ["production", "prod"].includes(process.env.NODE_ENV);
const plugins = [];
if (IS_PROD) plugins.push("transform-remove-console")

module.exports = {
  presets: [
    '@vue/cli-plugin-babel/preset'
  ],
  plugins
}
  1. 使用uglifyjs-webpack-plugin
yarn add uglifyjs-webpack-plugin -D

添加vue.config.js:

const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
const IS_PROD = ["production", "prod"].includes(process.env.NODE_ENV);

module.exports = {
  configureWebpack: config => {
    if (IS_PROD) {
      const plugins = []
      plugins.push(
        new UglifyJsPlugin({
          uglifyOptions: {
            compress: {
              drop_console: true, //注释console.log
              drop_debugger: false,
              pure_funcs: ['console.log'] //移除console
            }
          },
          sourceMap: false,
          parallel: true
        })
      )
      config.plugins = [...config.plugins, ...plugins]
    }
  }
}

参考:去除console.log

⬆️:  回到顶部

✅  配置CSS Modules

@vue/cli已经集成了CSS Modules,可以通过 <style module> 达到开箱即用。但如果想去掉文件名中的 .module或自定义生成 CSS Modules 模块的类名,还需要配置vue.config.js。

// vue.config.js
module.exports = {
  css: {
    requireModuleExtension: false, // 去掉文件名中的 .module
    loaderOptions: {
      css: {
        modules: {
          // 自定义类名,name:CSS Modules所在的文件名;local:原定的类名
          localIdentName: '[name]__[local]___[hash:base64:5]' 
        }
      }
    }
  }
}

注意:在将css-loader升级到版本3之后,yarn run serve之后会报错,认为localIdentName是无效的选项。是因为localIdentName选项需要嵌套在modules选项中。update yarn packages & update get_style_rule to handle [email protected]

Module build failed (from ./node_modules/css-loader/dist/cjs.js):
ValidationError: Invalid options object. CSS Loader has been initialised using an options object that does n
ot match the API schema.
 - options has an unknown property 'localIdentName'. These properties are valid:
   object { url?, import?, modules?, sourceMap?, importLoaders?, localsConvention?, onlyLocals? }
    at validate (C:\Users\chenweihuan\Desktop\demo\vue-demo1\node_modules\css-loader\node_modules\schema-uti
ls\dist\validate.js:85:11)
    at Object.loader (C:\Users\chenweihuan\Desktop\demo\vue-demo1\node_modules\css-loader\dist\index.js:34:2
8)

推荐阅读:深入理解vue的scoped和module原理
参考: vue-cli#css-modules

⬆️:  回到顶部

✅  向所有 Less 样式传入共享的全局变量

使用less需要安装less和less-loader:

yarn add less less-loader -D
// 示例安装的版本:"less": "^3.10.3", "less-loader": "^5.0.0"
  1. 配置less.globalVars
module.exports = {
  css: {
    loaderOptions: {
      less: {
        globalVars: {
          primary: 'blue'
        }
      }
    }
  }
}

less全局变量的使用:

<style lang="less">
.color {
  color: @primary;
}
</style>
// global.less
@primary:red;
  1. 利用style-resources-loader,简单粗暴(墙裂推荐):
vue add style-resources-loader

安装时会让你选择css的语言,选择less后,@vue/cli还会在vue.config.js自动生成一段样例代码,添加上路径即可:

// vue.config.js
const path = require('path')

module.exports = {
  pluginOptions: {
    'style-resources-loader': {
      preProcessor: 'less',
      patterns: [path.resolve(__dirname, "src/styles/global.less")]
    }
  }
}

参考:
vue-cli-plugin-style-resources-loader
向预处理器 Loader 传递选项

⬆️:  回到顶部

✅  向所有 Scss 样式传入共享的全局变量

使用scss需要安装sass-loader和node-sass:

yarn add sass-loader node-sass -D
// 示例安装的版本:"sass-loader": "^8.0.0", "node-sass": "^4.13.0"
  1. 配置vue.config.js:
// vue.config.js
module.exports = {
  css: {
    loaderOptions: {
      scss: {
        // 假设在src/styles有两个文件:global.scss和app.scss
        // @/ 是 src/ 的别名
        // `scss` 语法会要求语句结尾必须有分号,不然会报错
        prependData: `
          @import "~@/styles/global.scss";
          @import "~@/styles/app.scss";
        `
      }
    }
  }
}

scss全局变量的使用:

// app.scss
$color: blue;
<!-- App.vue -->
<style lang="scss">
.blue{
  color: $color;
}
</style>
  1. 使用style-resources-loader即可,简单粗暴:
vue add style-resources-loader
// vue.config.js
const path = require('path')

module.exports = {
  pluginOptions: {
    'style-resources-loader': {
      preProcessor: 'scss',
      patterns: [path.resolve(__dirname,'src/styles/app.scss')]
    }
  }
}

⬆️:  回到顶部

✅  向所有 Sass 样式传入共享的全局变量

使用style-resources-loader即可,简单粗暴:

vue add style-resources-loader
// vue.config.js
const path = require('path')

module.exports = {
  pluginOptions: {
    'style-resources-loader': {
      preProcessor: 'sass',
      patterns: [path.resolve(__dirname,'src/styles/app.sass')]
    }
  }
}

sass的全局变量使用:

// app.sass
$primary: green;
<!-- App.vue -->
<style lang="sass">
.container 
  color: $primary;
</style>

⬆️:  回到顶部

✅  向所有 Stylus 样式传入共享的全局变量

使用stylus需要安装stylus和stylus-loader:

yarn add stylus stylus-loader -D
// 示例安装的版本:"stylus": "^0.54.7", "stylus-loader": "^3.0.2"
  1. 配置vue.config.js:
// vue.config.js
module.exports = {
  css: {
    loaderOptions: {
      stylus: {
        // 假设在src/styles有两个文件:mixins.styl和app.styl
        import: [
          '~@/styles/mixins.styl',
          '~@/styles/app.styl'
        ]
      }
    }
  }
}

stylus全局变量的使用:

// app.styl
font = 20px;
<style lang="stylus">
.font {
  font-size: font;
}
</style>
  1. 使用style-resources-loader即可,简单粗暴:
vue add style-resources-loader
// vue.config.js
const path = require('path')

module.exports = {
  pluginOptions: {
    'style-resources-loader': {
      preProcessor: 'stylus',
      patterns: [path.resolve(__dirname,'src/styles/mixins.styl')]
    }
  }
}

⬆️:  回到顶部

✅  配置proxy代理解决跨域

如果你的前端应用和后端 API 服务器没有运行在同一个主机上,会出现跨域问题,你需要在开发环境下将 API 请求代理到 API 服务器。

// vue.config.js
module.exports = {
  devServer: {
    open: false, // 是否打开浏览器
    host: "0.0.0.0", // 可让你的应用跑在不同的机器上,使用localhost或IP访问
    proxy: {
      // 仅代理/api和/api2开头的接口
      "/(api|api2)": {
        target:
          "http://...:4000" // 目标代理接口地址
      }
    }
  }
};

⬆️:  回到顶部

✅  解决第三方包的IE11兼容

使用vue create构建项目后,已经能解决本地开发的IE11兼容问题,但并不能解决第三方库的IE11兼容问题。@babel/polyfill即将被废弃,使用core-jsregenerator-runtime代替。

  1. 全局引入
yarn add core-js regenerator-runtime -S
// main.js
import "core-js/stable";
import "regenerator-runtime/runtime";
// .babelrc
module.exports = {
  presets: [
    ['@vue/cli-plugin-babel/preset', { useBuiltIns: 'entry' }]
  ]
}
  1. 按需引入
    默认情况下 babel-loader 会忽略所有 node_modules 中的文件。如果你想要通过 Babel 显式转译一个依赖,可以在transpileDependencies这个选项中列出来。假如是因为引入vuex-pathify包的问题,配置如下:
// vue.config.js
module.exports = {
  transpileDependencies: [
    'vuex-pathify'
  ]
}

参考:
core-js @babel/polyfill
vue-cli文档 - transpileDependencies

⬆️:  回到顶部

✅  使用web worker

在vue里使用web worker,下面是一个构建部门树的核心代码:

// tree.worker.js
const nest = (items, code = 0, link = 'parentCode') => { // code就是老爸的code,大型认爹现场
  return items
    .filter(v => v[link] === code)
    .map(v => ({ ...v, children: nest(items, v.code) }))
}
self.addEventListener('message', (e) => { // self代表子线程自身,即子线程的全局对象。
  let { data } = e
  let { type, root } = data
  if (type === 'BUILD') {
    const tree = nest(root)
    self.postMessage({
      type,
      payload: {
        root: tree
      }
    })
  }
}, false)

// App.vue
import treeWorker from './tree.worker.js'
let worker = new treeWorker()
export default {
  mounted () {
    worker = new treeWorker()
    worker.addEventListener('message', this.handlerMessage)
    
    // 清除worker监听
    this.$once('hook:beforeDestroy',()=>{
      worker.removeEventListener('message',this.handlerMessage)
      worker.terminate()
    })

    // 请求后台数据拿到原始部门data
    setTimeout(() => {
      worker.postMessage({
        type: 'BUILD',
        root: data
      })
    })
  },
  methods: {
    handlerMessage(e){
      console.log(e)
    }
  }
}

安装worker-loader,否则会报错"export 'default' (imported as 'treeWorker') was not found in './tree.worker'

yarn add worker-loader -D

修改vue.config.js配置:

// vue.config.js
module.exports = {
  chainWebpack: config => {
    // 解决重新刷新页面或者重开启devServe都只取缓存,xx.work.js不更新的问题。
    // 具体讨论参考issues:https://github.com/webpack-contrib/worker-loader/issues/195
    config.module.rule('js').exclude.add(/\.worker\.js$/)
    
    // 使用worker-loader编译.worker.js文件
    config.module
      .rule('worker')
      .test(/\.worker\.js$/)
      .use('worker-loader')
      .loader('worker-loader')
      .options({
        name: '[name].worker.js'
      })
      .end()
  }
}

⬆️:  回到顶部

✅  dart-sass替换node-sass

解决 yarn 时,卡死在node-sass这里。

yarn remove node-sass
yarn add sass -S

修改vue.config.js配置:

// vue.config.js
module.exports = {
  css: {
    loaderOptions: {
      sass: {
        implementation: require('sass')
      }
    }
  }
}

参考:
https://dev.to/helleworld_/integrating-dart-node-sass-in-vuejs-4o39

⬆️:  回到顶部

✅  开启CDN加速

不用区分测试环境还是生产环境,统一都用cdn即可。修改index.html:

<!DOCTYPE html>
<html>
<head>
    ...
    <!-- element还需引入css文件 -->
    <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
</head>
<body>
    <div id="app"></div>
    <!-- built files will be auto injected -->
    <script src="https://unpkg.com/[email protected]/dist/vue.runtime.min.js"></script>
    <script src="https://unpkg.com/[email protected]/dist/vuex.min.js"></script>
    <script src="https://unpkg.com/[email protected]/dist/vue-router.min.js"></script>
    <script src="https://unpkg.com/element-ui/lib/index.js"></script>
</body>
</html>

修改vue.config.js配置:

// vue.config.js
module.exports = {
    configureWebpack: {
        externals: {
            vue: "Vue",
            vuex: "Vuex",
            "vue-router": "VueRouter",
            "element-ui": "ELEMENT"
        }
    }
};

打包后抛到服务器上,打开开发者工具的network,如果看到http请求cdn,那么就代表配置成功了。但有可能会出现未知BUG,谨慎使用。

参考:开启CDN加速

⬆️:  回到顶部

✅  缩小打包作用域

// vue.config.js
module.exports = {
    configureWebpack: {
      resolve: {
        // 合理使用别名
        alias: {
          '@': path.resolve(__dirname, './src/components')
        },
        // 指定在这些目录里寻找引用的库,提高搜索效率
        modules: [
          path.resolve(__dirname, './node_modules')
        ],
        // 尽可能减少后缀尝试的可能性,默认值为:[".js", ".json"]
        extensions: ['.js'],
        // 只采用 main 字段作为入口文件描述字段 
        // 减少搜索步骤,需要考虑到所有运行时依赖的第三方模块的入口文件描述字段
        mainFields: ['main']
      }
    }
}

⬆️:  回到顶部

✅  echarts按需加载

  1. require(官方方案)
// 引入 ECharts 主模块
var echarts = require('echarts/lib/echarts');
// 引入柱状图
require('echarts/lib/chart/bar');
// 引入提示框和标题组件
require('echarts/lib/component/tooltip');
require('echarts/lib/component/title');
// 基于准备好的dom,初始化echarts实例
var myChart = echarts.init(document.getElementById('main'));
// 绘制图表
myChart.setOption({
    title: {
        text: 'ECharts 入门示例'
    },
    tooltip: {},
    xAxis: {
        data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子']
    },
    yAxis: {},
    series: [{
        name: '销量',
        type: 'bar',
        data: [5, 20, 36, 10, 10, 20]
    }]
});

具体参考按需引入 ECharts 图表和组件

  1. babel-plugin-equire

添加babel-plugin-equire插件:

yarn add babel-plugin-equire -S

编辑 .babelrc 文件:

{
  "plugins": [
    "equire"
  ]
}

新建文件 echarts.js :

const echarts = equire([
  'bar',
  'title',
  'tooltip'
])
export default echarts

在需要用到 echarts 的地方引入 echarts.js 文件:

import echarts from './echarts'

// 基于准备好的dom,初始化echarts实例
var myChart = echarts.init(document.getElementById('app'));
// 绘制图表
myChart.setOption({
  title: {
    text: 'ECharts 入门示例'
  },
  tooltip: {},
  xAxis: {
    data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子']
  },
  yAxis: {},
  series: [{
    name: '销量',
    type: 'bar',
    data: [5, 20, 36, 10, 10, 20]
  }]
});

⬆️:  回到顶部

✅  预加载、vue-meat-info

  1. @vue/cli
vue add prerender-spa

接下来跟着命令行操作即可。

// 哪一个路由需要进行预加载配置,逗号隔开,且只适用于history路由模式
? Which routes to pre-render? (separate with comma) (only with Vue Router history mode) /,/home

// 是否使用事件触发快照
? Use a render event to trigger the snapshot? Yes
? Use a headless browser to render the application? Yes

// 是否只在生产环境开启预渲染
? Only use prerendering for production builds? Yes

到这里就已经完成了,该添加的配置@vue/cli已经做完。跑一下npm run build,在dist里生成对应路由单独的HTML文件就是生效了(我这里是多生成一个文件 home.html)

  1. prerender-spa-plugin
npm install prerender-spa-plugin --save

配置vue.config.js:

// vue.config.js
const PrerenderSPAPlugin = require('prerender-spa-plugin');
const Renderer = PrerenderSPAPlugin.PuppeteerRenderer;
const path = require('path');

module.exports = {
  configureWebpack: () => {
    if (process.env.NODE_ENV !== 'production') return;
    return {
      plugins: [
        new PrerenderSPAPlugin({
          staticDir: path.join(__dirname, 'dist'),
          routes: ['/', '/home',],
          renderer: new Renderer({
            inject: {
              foo: 'bar'
            },
            headless: false,
            // 在 main.js 中 document.dispatchEvent(new Event('render-event')),两者的事件名称要对应上。
            renderAfterDocumentEvent: 'x-app-rendered'
          })
        })
      ]
    };
  },
}

配置main.js:

import Vue from 'vue'
import App from './App.vue'
import router from './router'
new Vue({
  router,
  render: h => h(App),
  mounted: () => document.dispatchEvent(new Event("x-app-rendered")),
}).$mount('#app')

预渲染的作用是什么?

如果你调研服务器端渲染 (SSR) 只是用来改善少数营销页面(例如 /, /about, /contact 等)的 SEO,那么你可能需要预渲染。无需使用 web 服务器实时动态编译 HTML(SSR),而是使用预渲染方式,在构建时简单地生成针对特定路由的静态 HTML 文件。优点是设置预渲染更简单,并可以将你的前端作为一个完全静态的站点。

既然是为了SEO,那么还需要注意Meta信息的变化,vue-meta-info是个很好的抉择。

npm install vue-meta-info --save

全局引入 vue-meta-info:

import Vue from 'vue'
import MetaInfo from 'vue-meta-info'

Vue.use(MetaInfo)

组件内静态使用 metaInfo:

<script>
  export default {
    metaInfo: {
      title: 'My Example App', // set a title
      meta: [{                 // set meta
        name: 'keyWords',
        content: 'My Example App'
      }]
      link: [{                 // set link
        rel: 'asstes',
        href: 'https://assets-cdn.github.com/'
      }]
    }
  }
</script>

如果你的 title 或者 meta 是异步加载的,也可以的,参考处理 Vue 单页面 Meta SEO的另一种思路

参考:
vue-cli-plugin-prerender-spa
Vue-Cli3.0怎么使用预渲染怎么配置prerender-spa-plugin

⬆️:  回到顶部