vue.config.js 基本配置
module.exports = {
publicPath: './', // 默认为'/',
outputDir: process.env.outputDir || 'dist', // 'dist', 生产环境构建文件的目录
assetsDir: '', // 相对于outputDir的静态资源(js、css、img、fonts)目录
lintOnSave: false, // eslint
runtimeCompiler: true, // 是否使用包含运行时编译器的 Vue 构建版本
productionSourceMap: false, // 生产环境的 source map
parallel: require('os').cpus().length > 1,
pwa: {}
}
自定义路径别名
const path = require('path')
const resolve = dir => path.join(__dirname, dir)
module.exports = {
chainWebpack: config => {
// 添加别名
config.resolve.alias
.set('@', resolve('src'))
.set('assets', resolve('src/assets'))
.set('components', resolve('src/components'))
.set('views', resolve('src/views'))
.set('static', resolve('src/static'))
}
}
修复热更新失效
module.exports = {
chainWebpack: config => {
// 修复HMR
config.resolve.symlinks(true)
}
}
配置 externals
module.exports = {
configureWebpack: config => {
config.externals = {
vue: 'Vue',
'element-ui': 'ELEMENT',
'vue-router': 'VueRouter',
vuex: 'Vuex',
axios: 'axios'
}
}
}
为 sass 提供全局样式以及全局变量
去除 console.log()
npm i babel-plugin-transfrom-remove-console -D
在babel.config.js
文件中添加
const prodPlugin = [] // 生产环境所需要用到的插件
if (process.env.NODE_ENV === 'production') {
prodPlugin.push([
'transform-remove-console',
{
// 保留error和warn
exclude: ['error', 'warn']
}
])
}
module.exports = {
plugins: [...prodPlugin]
}
移动端适配
① 将px
转换为rem
;② 将px
转换为vw
vuecli
创建的项目本身就自带postcss-pxtorem
安装插件yarn add amfe-flexible
、yarn add postcss-pxtorem
依赖项autoautoprefixer
版本为 8.0.0
// main.js
import 'amfe-flexible'
// .postcssrc.js
module.exports = {
// 配置使用 postcss-pxtorem 插件
// 作用:把 px 转为 rem
plugins: {
'postcss-pxtorem': {
rootValue: 192,
propList: ['*'],
selectorBlackList: ['.van-'], // 要忽略的选择器并保留为px。
propList: ['*'], // 将px更改为rem的属性。
minPixelValue: 2 // 设置要替换的最小像素值。
}
}
}
使用
.postcssrc.js
配置
module.exports = {
plugins: {
'postcss-pxtorem': {
rootValue: 32, // 换算的基数
selectorBlackList: ['.van-'], // 要忽略的选择器并保留为px。
propList: ['*'], // 将px更改为rem的属性。
minPixelValue: 2 // 设置要替换的最小像素值。
}
}
}
移动端调试
vConsole
是腾讯开发的一个用于调试移动端项目的插件。
yarn add vconsole
在main.js
中,将vconsole
添加到开发环境下使用,生产环境不会使用到。
import vconsole from 'vconsole'
if (proceee.env.NODE_ENV === 'development') {
new vconsole()
}

让moment
变得更小
const webpack = require('webpack')
module.expots = {
chainWebpack: config => {
// 优化moment 去掉国际化内容
config
.plugin('ignore')
// 忽略/moment/locale下的所有文件
.use(new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/))
}
}
此时因为去掉了所有所有的国际化内容,导致不能显示中文语言,需要单独引入
import moment from 'moment'
// 手动引入所需要的语言包
import 'moment/locale/zh-cn'
// 指定使用的语言
moment.locale('zh-cn')
开启 Gzip 压缩
new CompressionWebpackPlugin({
algorithm: 'gzip',
test: /\.(js|css)$/, // 匹配文件名
threshold: 10000, // 对超过10k的数据压缩
deleteOriginalAssets: false, // 不删除源文件
minRatio: 0.8 // 压缩比
})
本地代理
// const { HashedModuleIdsPlugin } = require('webpack')
module.exports = {
devServer: {
open: true, // 自动启动浏览器
host: '0.0.0.0', // localhost
port: 6090,
https: false,
hotOnly: true, // 热更新
proxy: {
'^/sso': {
target: process.env.VUE_APP_SSO, // 接口的域名
ws: true, //开启WebSocket
secure: false, // 如果是https接口,需要配置这个参数
changeOrigin: true // 如果接口跨域,需要进行此参数的配置
// http://localhost:8080/sso => http://192.168.1.28:3333/sso
},
'/api': {
changeOrigin: true,
target: 'http://192.168.1.28:3333',
// 重写路径
pathRewrite: {
'^/api': ''
}
// http://localhost:8080/api/login => http://192.168.1.28:3333/login
}
}
}
环境变量
// .env.dev
VUE_APP_TITLE="项目1-开发环境"
"scripts": {
"dev": "vue-cli-service serve --mode dev",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
console.log(process.env.VUE_APP_TITLE)
只打包改变的文件
const { HashedModuleIdsPlugin } = require('webpack')
module.exports = {
chainWebpack: config => {
if (process.env.NODE_ENV === 'production') {
const plugins = [new HashedModuleIdsPlugin()]
plugins.push()
}
}
}
页面加载进度条
安装npm i nprogress
// [main.js]
// 加载进度条包对应js和css
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
// axios请求拦截
axios.interceptors.request.use(config => {
NProgress.start() // 在request中展示进度条
// ......
})
axios.interceptors.request.use(config => {
NProgress.done() // 在response中隐藏进度
// ......
})
开启打包日志
安装npm i webpack-bundle-analyzer
module.exports = {
chainWebpack: config => {
if (process.env.NODE_ENV === 'production') {
config
.plugin('webpack-bundle-analyzer')
.use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin)
}
}
}
一份较完整的配置
const path = require('path')
const { HashedModuleIdsPlugin } = require('webpack')
const resolve = dir => path.join(__dirname, dir)
const externals = {
vue: 'Vue',
'vue-router': 'VueRouter',
vuex: 'Vuex',
'view-design': 'iview'
}
// cnd预加载
const cdn = {
dev: {
css: [
'https://unpkg.com/view-design@4.6.0-beta.4/dist/styles/iview.css'
],
js: []
},
// 生产环境
build: {
css: [
'https://unpkg.com/view-design@4.6.0-beta.4/dist/styles/iview.css'
],
js: [
'https://cdn.bootcdn.net/ajax/libs/vue/2.6.6/vue.min.js',
'https://cdn.bootcdn.net/ajax/libs/vue-router/3.5.1/vue-router.min.js',
'https://cdn.bootcdn.net/ajax/libs/vuex/3.6.2/vuex.min.js',
'https://unpkg.com/view-design@4.6.0-beta.4/dist/iview.min.js'
// 'https://cdn.bootcdn.net/ajax/libs/crypto-js/4.0.0/crypto-js.min.js'
]
}
}
module.exports = {
publicPath: process.env.NODE_ENV === 'production' ? './' : '/', // 默认为'/',
outputDir: process.env.outputDir || 'dist', // 'dist', 生产环境构建文件的目录
// assetsDir: 'assets', // 相对于outputDir的静态资源(js、css、img、fonts)目录
productionSourceMap: false, // 生产环境的 source map
devServer: {
open: true,
hotOnly: true
},
configureWebpack: config => {
const plugins = []
// 打包分析
if (process.env.NODE_ENV === 'production') {
// 打包时npm包转CDN
config.externals = externals
// 用于根据模块的相对路径生成 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('@', '')}`
}
}
}
}
}
}
return { plugins }
},
chainWebpack: config => {
config.resolve.symlinks(true)
// webpack 会默认给commonChunk打进chunk-vendors,所以需要对webpack的配置进行delete
config.optimization.delete('splitChunks')
config.resolve.alias
.set('@', resolve('src'))
.set('assets', resolve('src/assets'))
.set('components', resolve('src/components'))
.set('views', resolve('src/views'))
.set('static', resolve('src/static'))
.set('utils', resolve('src/utils'))
config.plugin('html').tap(args => {
if (process.env.NODE_ENV === 'production') {
args[0].cdn = cdn.build
args[0].prod = true
}
if (process.env.NODE_ENV === 'development') {
args[0].cdn = cdn.dev
}
args[0].title = process.env.title
return args
})
if (process.env.NODE_ENV === 'production') {
// 打包性能分析
config
.plugin('webpack-bundle-analyzer')
.use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin)
}
}
}
<% for (var i in
htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.css) { %>
<link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="stylesheet"/>
<% } %>
<% for (var i in
htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.js) { %>
<script src="<%= htmlWebpackPlugin.options.cdn.js[i] %>" async></script>
<% } %>
vuerouter
vue-router3
路由重复点击报错问题
const originalPush = Router.prototype.push
Router.prototype.push = function push(location) {
return originalPush.call(this, location).catch(err => err)
}