vue高级实战技巧-如何优化项目
一、路由的模块化与统一加载
1. 如何自动加载
require.context:批量require文件
(1)以业务为模块创建相应的模块目录:
mode1-------------------------模块文件夹
|--pages----------------------模版文件夹
|---- model1.index.vue--------模版文件
|---- model1.second.vue-------模版文件
|--index.routes.js------------此模块的路由文件
index.routes.js
let r = require.context("./page", true, /\.vue$/) // 路径,是否遍历子文件夹,文件正则
let arr = []
r.keys().forEach(key => {
let _keyarr = key.split('.')
if (key.indexOf('index') !== 1) {
arr.push({
path: _keyarr[1],
component: r(key).default
})
} else {
arr.push({
path: _keyarr[1] + '/' + _keyarr[2],
component: r(key).default
})
}
})
Router/index.js 总路由文件
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
let r = require.context("../components", true, /\.routes\.js$/)
let arr = []
r.keys().forEach(key => {
arr = qrr.concat(r[key].default)
})
export default new Router({
routes: [...arr]
})
路由参数问题:如果需要额外的参数配置,可以新建一个mode.json文件,设置配置信息,然后读取此文件,根据key来配置。
{
modelIndex: {mate: ***}
}
二、打包优化
打包速度优化的总结:
处理的内容多少 --> 处理步骤多少
能少处理的就少处理,例如一些静态资源可以通过CDN或者第三方线上地址引入,就不需要webpack进行打包了
能够减少一些处理步骤:例如开发环境下不用打包,生产环境下的source-map
dll优化:可以把第三方包进行预处理(能少处理的就少处理)–> 真正打包的不需要处理这些库;如一些第三方库vue,vue-router,axios,loadsh这些只需要集成一次,打包压缩一次就可以了,不需要每次都打包,从而减少打包的速度。
新建webpack.dll.js
const path = require('path')
const webpack = require('webpack')
const config = require('../config')
moudle.exports = {
entry: {
vendor: ['vue/dist/vue.esm.js', 'vue-router', 'axios', 'loadsh'] // 需要预处理的文件
},
output: {
path: path.join(__dirname, "../static/js"), // 打包后存放文件的路径
filename: "[name].dll.js",
library: "[name]_library" // plugin中需要使用
},
plugin: [
// 插件生成json文件,告诉webpack真正打包的时候忽略哪些已经dll处理的文件
new webpack.DllPlugin({
path: path.join(__dirname, ".", "[name]-manifest.json"),
name: "[name]_library" // 一定要与output中的library名字一致
})
]
}
package.json文件中增加运行脚本:
"script": {
"dll": "webpack --config build/webpack.dll.js"
}
npm run dll
Webpack.prod.conf.js(真正打包的配置文件)中需添加插件接受不需要再打包的第三方库:
plugins: [
new webpack.DllReferencePlugin({
context: path.join(__dirname, '..'),
manifest: require("./vendor-manifest.json")
})
]
三、为项目开发vue插件
1. 为什么要开发插件
提供全局自定义的操作:项目中会有一些特殊需求,插件就是为了解决这些需求的。它可以注入到每个组件的生命周期,然后自动做某些事情。
例如vue-router,vuex,使用时是通过Vue.use() // 表示直接调用传入的方法
function a() { console.log(1); }
a.install = function() { console.log("install"); }
Vue.use(a) // "install"
如果传入的参数是个方法,则直接执行此方法,如果此方法注册了install属性,且是个方法,则只执行install方法。
2. 具体使用
创建vuePlugin文件夹,下新建index文件
let a = {
install: function(vue) { // 通过Vue.use时,会传入一个参数vue
vue.mixin({ // 通过vue.mixin方法可以为每个组件注入data/methods/生命周期
data: {},
methods: {},
created: function() {}
})
}
}
module.exports = a
在main.js入口文件中引入插件
import vuePlugin from './vuePlugin'
Vue.use(vuePlugin)
3. 示例问题
项目vuex过大,导致打包结果过大 ,解决:按组件异步拆分加载vuex
创建store文件夹,新建modules文件夹存放不同功能模块异步加载的js,同时创建index.js入口文件
store>index.js(首屏加载的)
import Vue from 'vue'
import vuex from 'vuex'
Vue.use(vuex)
// 首页必须加载的vuex
export default new vuex.Store({
state: {
num: 1
}
})
store>modules>mode1Index.js(懒加载的文件)
export default {
state: {
num2: 123
}
}
vuePlugin>index.js
let a = {
install: function(vue) { // 通过Vue.use时,会传入一个参数vue
vue.mixin({ // 通过vue.mixin方法可以为每个组件注入data/methods/生命周期
beforeCreate() {
if (this.$options.isVuex) { // 判断当前组件是否需要引入vuex
let name = this.$options.name
import('../store/modules/' + name).then(res => { // import的参数必须是字符串或者拼接字符串,不能直接是变量
this.$store.registerModule(this.$options.name, res.default) // 第一个参数:需要注册的vuex模块名称,第二个参数需要注入的内容
})
}
}
})
}
}
module.exports = a
mode1>pages>mode1Index.vue
export default {
name: 'mode1Index',
isVuex: true. // 可以是任意属性名,值也可以是数组等任意数据格式
}
在main.js文件中注册store
import store from './store'
new Vue({
store
})