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)
}
