在vue-cli3.0中,由于将webpack的基础配置全部内嵌了,那我们如何修改配置呢?当然,vue-cli3.0中,我们可以通过新建vue.config.js文件来修改,进行自定义配置。vue.config.js 也是一个可选的配置文件,如果项目的 (和 package.json 同级的) 根目录中存在这个文件,那么它会被 @vue/cli-service 自动加载。关于vue.config.js配置,在此自己测试时,做的一个简单记录,存档用。

官方文档:https://cli.vuejs.org/zh/config/

               https://cli.vuejs.org/zh/guide/webpack.html

一、基本的配置(端口、路径等)

文档:https://cli.vuejs.org/zh/config/#vue-config-js

在项目根目录下新建vue.config.js文件(有的代码是上一节环境变量配置所留,没删完),写入:

module.exports = {
    publicPath: '/', //基本路径
	//publicPath: process.env.NODE_ENV !== 'production' ? process.env.VUE_APP_URL : '/', //基本路径
	outputDir: 'dist',  //生产环境构建输出目录
	//outputDir: process.env.VUE_APP_outputDir  
	assetsDir: '',      //放置生成的静态资源 (js、css、img、fonts) 的 (相对于 outputDir 的) 目录
	lintOnSave: false, // 是否开启eslint在保存的时候检查 ,false不开启
	devServer: {
	   open: true,      // 启动服务后是否自动打开浏览器,true-每次启动都会打开新的
	   host: '0.0.0.0', // 允许外部ip访问
           port: 8081,      // 端口
           https: false,    // 是否启用https
        },
	//判断不同环境下使用不同配置
	configureWebpack: config =>{
	   if (process.env.NODE_ENV === "development") {
		config.devtool = 'source-map';
	    } else if (process.env.NODE_ENV === "production") {
			config.devtool = "eval-source-map";
	    }
	}
}

二、开发时的跨域设置

文档:https://cli.vuejs.org/zh/config/#devserver-proxy

         https://www.webpackjs.com/configuration/dev-server/#devserver

         webpack-dev-server配置 

         https://webpack.docschina.org/configuration/dev-server/


具体可以根据文档配置自己的需求。

如果我们有单独的后端开发服务器 API,并且希望在同一域名下发送 API 请求 ,则代理某些 URL 会很有用。

//webpack-dev-server 相关配置
devServer: {
	// 跨域代理配置---可配置更多控制行为
	proxy: {
	  '/api': {
		target: 'http//api.qianduan8.com',
		ws:true,            //是否允许跨域
		secure: false,      // 如果是https接口,需要配置这个参数
		changeOrigin: true,  // 如果接口跨域,需要进行这个参数配置
		pathRewrite:{
			'^/api':''  //重写路径--匹配 /api ,然后变为'',
		}
	  }
	}
}
比如我们请求/api/users  现在会被代理到请求 http//api.qianduan8.com/api/users ,重写后呢?变成http//api.qianduan8.com/users

使devServer.before加载本地json数据

devServer.before提供在服务器内部的所有其他中间件之前执行定制中间件的功能。这可以用来定义自定义处理程序。

比如我们项目根目录下建一个data文件夹,里面有一个goods.json文件。

如何使用呢?我们先在vue.config.js最上面引入

const goods = require('./data/goods.json');
然后在devServer配置:

before(app){
    //访问地址:http://localhost:8081/api/goods
    app.get('/api/goods', function(req, res) {
	res.json(goods);
    });
}
运行npm run serve,然后我们在浏览器里输入http://localhost:8081/api/goods  就可以拿到数据了。

三、css相关配置

文档:https://cli.vuejs.org/zh/guide/css.html#css-modules

         https://vue-loader.vuejs.org/zh/guide/css-modules.html

//css相关配置
css: {
	extract: true,      // 是否使用css分离插件 ExtractTextPlugin。Default: 生产环境下是 true,开发环境下是 false
	sourceMap: false,   // 开启 CSS source maps?
	modules: false,      //是否开启css-modules模式, 默认值为flase
	loaderOptions: {
		css: {
		    // 这里的选项会传递给 css-loader
		}, 
		postcss: {
		    // 这里的选项会传递给 postcss-loader
		},
		// css预设器配置项
		sass: {
		    // @/ 是 src/ 的别名
		    data: `@import "~@/variables.css";`  // 向所有 Sass 样式传入共享的全局变量
		}		  
	} 
}

1、全局引入sass\less

sass全局引入用上面的就可以了,

相关文档: https://cli.vuejs.org/zh/guide/css.html#css-modules

如果是less的话会有点不同,需安装style-resources-loader插件

vue add style-resources-loader
然后会自动在vue.config.js生成基础代码,配置上我们的less地址就可以了。如:

    pluginOptions: {
      'style-resources-loader': {
        preProcessor: 'less',
			patterns: [
				path.resolve(__dirname, './src/assets/css/common.less'),
				path.resolve(__dirname, './src/assets/css/base.less')
			]
      }
    }

有一点注意一下,全局less的背景图片路径可以如下引用

background: url(~@/assets/images/icon.png);

四、启用CDN加速引入 

对于一些常用的不经常改动的库,比如: vue、vuex、vue-router、axios等等,或者一些UI库比如vuetify,我们可以用CDN的方式引入,让webpack不对他们进行打包,这样可以减少文件大小,也可以节约一点服务器的带宽。

const externals = {
	vue: 'Vue',
	'vue-router': 'VueRouter',
	vuex: 'Vuex',
	vuetify: 'vuetify',
	axios: 'axios'
}
const cdn = {
	// 开发环境
	dev: {
		css: [
		    'https://cdn.bootcss.com/vuetify/1.5.5/vuetify.min.css'
		],
		js: [
		    'https://cdn.bootcss.com/vuetify/1.5.5/vuetify.min.js'
		]
	},
	// 生产环境
	build: {
		css: [
		    'https://cdn.bootcss.com/vuetify/1.5.5/vuetify.min.css'
		],
		js: [
		    'https://cdn.bootcss.com/vue/2.6.10/vue.min.js',
		    'https://cdn.bootcss.com/vue-router/3.0.3/vue-router.min.js',
		    'https://cdn.bootcss.com/vuex/3.0.1/vuex.min.js',
		    'https://cdn.bootcss.com/axios/0.19.0/axios.min.js',
		    'https://cdn.bootcss.com/vuetify/1.5.5/vuetify.min.js'
		]
	}
}
			
configureWebpack: config => {
    if (process.env.NODE_ENV === "production") {
	//externals里的模块不打包
	Object.assign(config, {
	    externals: externals
	})
    }
},
chainWebpack: config => {
    // 对vue-cli内部的 webpack 配置进行更细粒度的修改
    config.plugin('html').tap(args => {
        if (process.env.NODE_ENV === 'production') {
            args[0].cdn = cdn.build
        }
        if (process.env.NODE_ENV === 'development') {
            args[0].cdn = cdn.dev
        }
        return args
    })
}
然后在入口index.html页面使用esj语法可以读取到配置中的参数,代码如下:
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
    <title>vue-cli31</title>
    <!-- 使用CDN加速的CSS文件,配置在vue.config.js下 -->
    <% for (var i in
        htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.css) { %>
    <link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="preload" as="style" />
    <link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="stylesheet" />
    <% } %>
  </head>
  <body>
    <noscript>
      <strong>We're sorry but vue-cli31 doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
    </noscript>
    <div id="app"></div>
    <!-- built files will be auto injected -->
      <!-- 使用CDN加速的JS文件,配置在vue.config.js下 -->
      <% for (var i in
          htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.js) { %>
      <script src="<%= htmlWebpackPlugin.options.cdn.js[i] %>"></script>
      <% } %>
  </body>
</html>
	   

因为html-webpack-plugin是webpack的一个插件,可以动态的创建和编辑html内容,在webpack中使用cdn是在打包生成静态资源的时候做处理,主要原理是使用html-webpack-plugin动态插入cdn链接。如link标签和script标签。

参考的文章:基于vue-cli3.0构建功能完善的移动端架子

五、修改uglifyOptions去除console来减少文件大小

安装uglifyjs-webpack-plugin

npm i -D uglifyjs-webpack-plugin

安装后在vue.config.js中引入

const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
加入如下代码:
configureWebpack: config => {
    if (process.env.NODE_ENV === 'production') {
              // 上线压缩去除console等信息
		config.plugins.push(
			new UglifyJsPlugin({
				uglifyOptions: {
					compress: {
						warnings: false,
						drop_console: true,
						drop_debugger: false,
						pure_funcs: ['console.log'] // 移除console
					}
				},
				sourceMap: false,
				parallel: true
			})
		)
    }
  }

compress参数文档:https://github.com/mishoo/UglifyJS2/tree/harmony#compress-options

六、开启Gzip

Gzip是一种压缩技术。它将浏览器请求的文件先在服务器端进行压缩,然后传递给浏览器,浏览器解压之后再进行页面的解析工作。在服务端开启Gzip支持后就可以自行压缩了,当然我们前端也可以提前提供资源压缩包,可以更加优化,通过compression-webpack-plugin插件build提供压缩。

npm install compression-webpack-plugin --save-dev
const CompressionWebpackPlugin = require('compression-webpack-plugin');
const productionGzipExtensions = ['js', 'css'];
configureWebpack: config => {
	if (process.env.NODE_ENV === 'production') {
		// 打包生产.gz压缩包
		config.plugins.push(new CompressionWebpackPlugin({
			algorithm: 'gzip',
			test: new RegExp('\\.(' + productionGzipExtensions.join('|') + ')$'),
			threshold: 10240,
			minRatio: 0.8
		}))
	}
}
七、设置alias目录别名

resolve.alias用来创建 import 或 require 的别名,来确保模块引入变得更简单,因为有时候我们项目中使用引入文件有时候路径比较深,所以可以使用webpack的别名alias配置来解决。

官方文档:https://www.webpackjs.com/configuration/resolve/#resolve-alias

如果没有安装path模块需要先安装path

npm i -D path
const path = require('path');
function resolve (dir) {
	return path.join(__dirname, dir)
}
chainWebpack: config => {
	config.resolve.alias
		.set('_c', resolve('src/components'))
		.set('api', resolve('src/api'))
}

比如:components目录下有一个HelloWord.vue文件,在App.vue里我们就可以这样引用了。

import HelloWorld from '_c/HelloWorld'