为什么要了解Vue CLI 4.0 webpack配置?
使用Vue.js 必然需要使用Vue CLI;使用Vue CLI,不可避免的会涉及到webpack的使用。而webpack最关键的地方就是配置了。Vue CLI 是基于webpack构建起来的Vue手脚架。俗话说得好,磨刀不误砍柴工。想要提高在Vue上的编码速度,必然需要一个好的Vue CLI;想要拥有一个好的Vue CLI,肯定离不开好的webpack配置。所以说,了解Vue CLi的配置方法,对Vue 开发人员来说是很重要的。可能有人说,Vue CLI 默认配置就很好用呀!并不需要去配置自己的webpack。
诚然,Vue CLI官方的配置已经很好用的。但是Vue CLI 默认配置是面向大众的。说白了就是一款满足大众开发需求的webpack方案。然而,总顶不住某些奇葩的需求。面对这些特殊的需求,可能默认配置就不适用了。例如,项目部署上线的路径问题、跨域调试问题、项目打包优化问题等等。
Vue CLI webpack 的历史
Vue CLI 有一个重要的节点,那就是Vue CLI 3.0。在Vue CLI 3.0 之前,webpack 的配置文件叫做webpack.config.js,用Vue CLI 创建项目时会自动生成。这时的Vue CLI 的webpack配置方法跟webpack官方配置方法一样。但是到了Vue CLI 3.0之后(包括Vue CLI 3.0),配置文件就变成了vue.config.js。Vue CLI 不再默认生成webpack的配置文件了。想要手动配置webpack,就需要用户在项目根目录手动去添加vue.config.js。而且,Vue 还对webpack配置做了自己的定制,增加了一些定制属性,配置的方法跟webpack官方提供的方法有了一些不同。
本系列讲的是什么?
本系列是一个Vue CLI 4.0 webpack的入门专栏,主要介绍的是Vue CLI 4.0 webapck基础内容,将会结合Vue CLI 4.0 的官方文档,对Vue CLI 4.0 的webpack的一些常用配置属性进行讲解,辅以配置属性使用代码案例。此外,还将提供一个完整的基础配置范例。
关于vue.conmfig.js,官方说明如下:
vue.config.js 是一个可选的配置文件,如果项目的 (和 package.json 同级的) 根目录中存在这个文件,那么它会被 @vue/cli-service 自动加载。你也可以使用 package.json 中的 vue 字段,但是注意这种写法需要你严格遵照 JSON 的格式来写。
- 第一点:vue.config.js是可选配置文件;
- 第二点:vue.config.js必须存在与项目根目录,不然无法生效。这里要提及的一点,项目的根目录是更具package,json文件来定义的。
- 第三点:Vue.config.js会被自动加载(前提是位置正确)。所以我们只需要添加好vue.config.js,并做好配置就行了。
如下图,这是添加好vue.config.js的项目了。可以看到vue.config.js与package.json在同一层目录。
小知识
实际上,VueCLI 3.0及以上构建的项目是有webpack.config.js的,只是被Vue隐藏起来了。里面是VueCLI的默认webpack配置。而vue.config.js是vue 对webpack.config.js的扩展文件。最终编译时,vue.config.js会被合并到webpack.config.js中。
如果我们想查看最终编译的webpack配置,可进行一下操作:
- vue inspect
在控制台的Vue项目根目录下运行上面代码,webpack配置将在控制台打印出来。
如果,想要webpack配置存储到一个文件中,可以这样:
- vue inspect > output.js
这样webpack配置将存在到output.js中。(output.js存储的文件路径为项目根目录)
vue-cli3+/4+ 脚手架搭建完成后,项目目录中没有 vue.config.js 文件,需要手动创建 。
vue.config.js 是一个可选的配置文件,如果项目的 (和 package.json 同级的) 根目录中存在这个文件,那么它会被 @vue/cli-service 自动加载。你也可以使用 package.json 中的 vue 字段,但是注意这种写法需要你严格遵照 JSON 的格式来写。
开始:创建vue.config.js
想要在Vue CLI 4.0 配置自己的webpack。第一步,要做的就是创建vue.config.js。在根目录中手动创建 vue.config.js 文件
一、publicPath
- Type:
string
- Default:‘/’
作用:
部署应用包时的基本 URL,用法和 webpack 本身的 output.publicPath 一致。
注意:这个值也可以被设置为空字符串 (' ') 或是相对路径 ('./'),这样所有的资源都会被链接为相对路径,这样打出来的包可以被部署在任意路径。
//部署应用包时的基本 URL;
//这个值也可以被设置为空字符串 ('') 或是相对路径 ('./'),
//这样所有的资源都会被链接为相对路径,这样打出来的包可以被部署在任意路径
用法:
module.exports = { publicPath: './' //部署应用包时的基本URL }
官方文档说明:
部署应用包时的基本 URL。
用法和 webpack 本身的 output.publicPath 一致,但是 Vue CLI 在一些其他地方也需要用到这个值,所以请始终使用 publicPath 而不要直接修改 webpack 的 output.publicPath。
默认情况下,Vue CLI 会假设你的应用是被部署在一个域名的根路径上,例如https://www.my-app.com/。
如果应用被部署在一个子路径上,你就需要用这个选项指定这个子路径。例如,如果你的应用被部署在 https://www.my-app.com/my-app/,则设置 publicPath 为 /my-app/。
这个值也可以被设置为空字符串 (' ') 或是相对路径 ('./'),这样所有的资源都会被链接为相对路径,这样打出来的包可以被部署在任意路径。
官方文档解析
看完官方文档是否一脸蒙蔽?什么是部署应用包时的基本 URL?
什么是域名的根路径?
别急,容我慢慢道来。
首先,我们来看两个字眼:部署、域名
从这两个字眼我们可以推断出, publicPath与服务器有关系了。
什么?你看不出。没关系,看不出,你就默认它有关吧!
项目到部署服务器
当我们完成项目开发要对外开放时,就需要把打包好的项目文件上传到服务器进行部署操作。流程大致如下:
- 项目文件打包
- 服务器安装配置 Web Server 服务器(软件)。如:IIS、Apache(下面,我将默认以Apache进行讲解)
- 将打包好的项目文件上传到 Web服务器的域名根目录下,Apache 默认为 www 目录
用户访问服务器流程说明:
访问网站我们都很熟悉,无非就是在浏览器输入对应网址就可以访问网址了。那服务器是如何工作的呢?
简单来说,当 Apache 接收到用户发来的http request 请求时,会自动到 www 目录下寻找对应的资源,然后将用户需要的资源再 Response 响应发送回去。拿官方例子来说,我们有一个对外的网址https://www.my-app.com/ 。用户只要通过这个网址访问我们的服务器,Web 服务器就会自动到 www 目录里获取对应的资源。假设,www 目录有这个test.html 文件。用户要访问这个文件,那么只需要https://www.my-app.com/test.html 就可以访问到了。实际上,就是www/test.html。也就是说,https://www.my-app.com/替代了www/
假设,www 目录结构现在变成下面这样,我们该这么访问呢?
访问test.html就变成了:https://www.my-app.com/my-app/test.html
如果test.html 使用pic.jpg 图片。写法就变成:<img src='/my-app/pic.jpg'/>
看到这里,可能就有人满脸疑惑。
src='/my-app/pic.jpg' ?
/my-app/pic.jpg ??
确定没错???
没错!!!
用户从浏览器访问pic.jpg 路径跟访问test.html 一样:https://www.my-app.com/my-app/pic.jpg
test.html 要使用pic.jpg,那必然先得让用户浏览器访问到pic.jpg。这一点,我们可以在任何一个网站可以看到。
一般的,在项目开发中写法应该将src写成:./pic.jpg。这是一种相对路径的写法。但要注意的是,相对路径还有另外两种写法:
- …/是父级目录
- /是根目录
关于相对路径的写法,请参考:相对路径的三种写法,即,如下:
1、./是当前目录
2、../是父级目录
3、/是根目录
根目录指逻辑驱动器的最上一级目录,它是相对子目录来说的。打开“我的电脑”,双击C盘就进入C盘的根目录,双击D盘就进入D盘的根目录。其它类推。根目录在文件系统建立时即已被创建,其目的就是存储子目录(也称为文件夹)或文件的目录项。
使用另外两种写法,应写成:
../my-app/pic.jpg
/my-app/pic.jpg
可能,对于最后一种的写法,大家会存在疑惑。
根目录为什么是 www ?
对于这一点,大家要注意的是这个根目录对应的Apache服务器的域名根目录。
这时,可能就会又有人问了。既然如此,是不是每次部署服务器都要去手动改url?一个项目里有许许多多的url,每次部署都要改,会死人的呀!
当然不能这么麻烦啦!publicPath 就是为此而生的。publicPath设置的就是项目文件根路径相对www的那一部分路径。也就是/my-app/了。设置publicPath 后,项目打包是就会自动在src前面补上publicPath 的值。
如下图:
打包出来的结果:
可以看到,在所有的url前都自动补上了
/my-app/
。讲了这么多,总之一句话:
publicPath
设置的就是域名根目录
到项目文件根目录
间的url。在官方文档最后一段话写到,我们可以将
publicPath
设置为''
或者'./'
,这样打出来的包可以被部署在任意路径。
总结:
- publicPath 接收 string 类型的 value;默认值为 '/'(/是根目录)
- publicPath 设置的是部署应用包的基本 URL,不是项目打包出来的文件存放的位置。
- publicPath 也可以设置为''或者'./',设置成相对路径后可以任意部署。
二、outputDir
- Type: string
- Default: dist
作用:
设置项目打包生成的文件的存储目录,可以是静态路径也可以是相对路径。注意:相对路径是相对于项目文件当前的根路径。
//运行npm run build命令,进行打包时输出的文件目录;
//默认:dist目录
用法:
module.exports = { publicPath: './', //部署应用包时的基本URL outputDir: 'dist' //输出文件目录 }
三、assetsDir
- Type: string
- Default: ' '
作用:
设置放置打包生成的静态资源 (js、css、img、fonts) 的目录。注意: 该目录是相对于 outputDir 。
//放置打包生成的静态资源 (js、css、img、fonts) 的目录;
//会在dist目录下创建生成static目录,
//来存放我们静态生成的js、css、img、fonts文件
用法:
module.exports = { publicPath: './', //部署应用包时的基本URL outputDir: 'dist', //输出文件目录 assetsDir: 'static' //放置打包生成的静态资源 (js、css、img、fonts) 的目录 }
四、indexPath
- Type: string
- Default: 'index.html'
作用:
用于设定打包生成的 index.html 文件的存储位置注意:
- 该路径若是相对路径,则相对于 outputDir;当然,也可以是一个绝对路径;
- 路径一定要以文件名+后缀结尾,最好以index,html结尾。
//用于设定打包生成的index.html文件的存储位置;
//会在dist目录下创建生成index.html文件;
//默认:index.html文件
用法:
module.exports = { publicPath: './', //部署应用包时的基本URL outputDir: 'dist', //输出文件目录 assetsDir: 'static', //放置打包生成的静态资源 (js、css、img、fonts) 的目录 indexPath: 'index.html' //用于设定打包生成的index.html文件的存储位置 }
五、filenameHashing
- Type:
boolean
- Default:
true
设置打包生成的静态资源的文件名中是否加入
hash
以便控制浏览器缓存问题。//设置打包生成的静态资源的文件名中是否加入hash以便控制浏览器缓存问题
//生成的静态资源在它们的文件名中包含了hash以便更好的控制缓存
//默认:true
module.exports = { publicPath: './', //部署应用包时的基本URL outputDir: 'dist', //输出文件目录 assetsDir: 'static', //放置打包生成的静态资源 (js、css、img、fonts) 的目录 indexPath: 'index.html', //用于设定打包生成的index.html文件的存储位置 filenameHashing: true, //设置打包生成的的静态资源的文件名中是否加入hash以便控制浏览器缓存问题 }
六、lintOnSave
- Type:
boolean
|‘warning’
|‘default’
|‘error’
- Default:
true
作用:
是否在保存的时候使用 `eslint-loader` 进行检查。
value:
- false:关闭每次保存都进行检测
- true:开启每次保存都进行检测,效果与warning一样
- 'warning':开启每次保存都进行检测,lint 错误将显示到控制台命令行,而且编译并不会失败。
- 'error':开启每次保存都进行检测,lint 错误将显示到浏览器页面上,且编译失败。
- 'default':同'error'
注意:
有效的值:`ture` | `false` | `"error"`, 当设置为 `"error"` 时,检查出的错误会触发编译失败。
//设置是否在开发环境下每次保存代码时都启用eslint验证
//eslint-loader是否在保存的时候检查
//默认:true
用法:
module.exports = { publicPath: './', //部署应用包时的基本URL outputDir: 'dist', //输出文件目录 assetsDir: 'static', //放置打包生成的静态资源 (js、css、img、fonts) 的目录 indexPath: 'index.html', //用于设定打包生成的index.html文件的存储位置 filenameHashing: true, //设置打包生成的的静态资源的文件名中是否加入hash以便控制浏览器缓存问题 lintOnSave: true, //设置是否在开发环境下每次保存代码时都启用 eslint验证 }
七、devServer
- Type:
Object
作用:
通过devServer,可以在NodeJs架设起临时的服务器用于项目的运行与调试。
用法:
const path = require('path') const UglifyJsPlugin = require('uglifyjs-webpack-plugin') //导出了一个包含各选项的对象 module.exports = { publicPath: './', //部署应用包时的基本URL outputDir: 'dist', //输出文件目录; assetsDir: 'static', //静态资源目录 indexPath: 'index.html', //设置index.html filenameHashing: true, //设置打包生成的静态资源的文件名中是否加入hash以便控制浏览器缓存问题 lintOnSave: true, //是否在保存的时候使用 `eslint-loader` 进行检查 productionSourceMap: false, //设置生产环境的 source map 开启与关闭 devServer: { open: true, //npm run dev启动项目后是否自动打开浏览器 host: 'localhost', //匹配本机IP地址(默认是0.0.0.0或localhost) port: 8050, //端口号 ,默认:8080 hot: true, //是否开启热更新(局部刷新,不刷新整个页面) inline: true, //用于设置代码保存时是否自动刷新页面 https: true, //是否启用https compress: true, //是否启动gzip压缩,用于减少服务器向前端传输的数据量,提高浏览的速度 overlay: { //错误、警告在页面弹出 warnings: false, errors: true }, proxy: { '/api': { target: 'http://localhost:8050', //跨域的域名 changeOrigin: true, //是否开启跨域 ws: true, //是否支持websocket secure: true, //如果是https接口,需要配置这个参数 pathRewrite: { '^/api': '' //重写地址 } } } }, configureWebpack: config => { if (process.env.NODE_ENV === 'production') { //为生产环境修改配置 config.mode = 'production' //打包文件大小设置 config["performance"] = { "maxEntrypointSize": 10000000, "maxAssetSize": 30000000 } config.optimization.minimizer = [ //打包时去除打印信息(console) new UglifyJsPlugin({ uglifyOptions: { // 删除注释 output: { comments: false }, // 删除console debugger 删除警告 compress: { drop_console: true, //console drop_debugger: true, pure_funcs: ['console.log'] //移除console }, warnings: false } }) ] } else { //为开发环境修改配置 config.mode = 'development' } Object.assign(config, { //开发生产共同配置别名 resolve: { alias: { '@': path.resolve(__dirname, './src'), '@c': path.resolve(__dirname, './src/components'), '@p': path.resolve(__dirname, './src/pages'), '@v': path.resolve(__dirname, './src/views'), } } }) }, chainWebpack: config => { config .plugin('html') .tap(args => { args[0].title = '后台管理系统'//修改项目名称 return args }) } }
八、productionSourceMap
- Type:
boolean
- Default:
true
作用:
设置生产环境的 source map 开启与关闭。
map文件的作用在于:项目打包后,代码都是经过压缩加密的,如果运行时报错,输出的错误信息无法准确得知是哪里的代码报错。有了map就可以像未加密的代码一样,准确的输出是哪一行哪一列有错。也就是说map文件相当于是查看源码的一个东西。如果不需要定位问题,并且不想被看到源码,就把productionSourceMap 置为false,既可以减少包大小,也可以加密源码。
用法:
module.exports = { publicPath: './', //部署应用包时的基本URL outputDir: 'dist', //输出文件目录 assetsDir: 'static', //放置打包生成的静态资源 (js、css、img、fonts) 的目录 indexPath: 'index.html', //用于设定打包生成的index.html文件的存储位置 filenameHashing: true, //设置打包生成的的静态资源的文件名中是否加入hash以便控制浏览器缓存问题 lintOnSave: true, //设置是否在开发环境下每次保存代码时都启用 eslint验证 productionSourceMap:false,//设置生产环境的 source map 开启与关闭 }
- 开启
productionSourceMap
后
- 未开启
productionSourceMap
后可以看出,开启
productionSourceMap
后,打包生成的 js 文件都有一个 .map 文件。这里要注意,只有 js 才有 .map 文件。扩展:
什么是
source map
?source map 直译过来就是资源地图。所以,source map的作用就是定位。source map定位的时浏览器控制台输出语句在项目文件的位置。
Vue打包后出现一些map文件的解决办法:
问题: 可能很多人在做vue项目打包,打包之后js中,会自动生成一些map文件,那我们怎么把它去掉不要呢?
1,运行 cnpm run build 开始打包
2,会在项目目录下自动创建dist目录,打包好的文件都在其中
解决办法:去src/config/index.js中改一个参数:
productionSourceMap:false
把这个改为false。不然在最终打包的文件中会出现一些map文件,map文件的作用在于:项目打包后,代码都是经过压缩加密的,如果运行时报错,输出的错误信息无法准确得知是哪里的代码报错。