前言
- 最近掘金上关于
webpack
的文章像是开了挂一般,疯狂的产出量着实让人望洋兴叹。这不,我这麽懒的人也都来凑个热闹,嘿嘿(黑人头像)! - 先大概说下下来到底干神马。本文默认你已经看过
webpack
官方文档或者一些上手的文章资料,说实话这方面的优质文章太多了,作为一个前端菜鸟的我就不在这里重复造轮子了,如果您还非要再去看下,得嘞,看官您这边请:从0到1教你撸一撸webpack、深入浅出Webpack、webpack中文文档。那咱干啥呢,请看标题【如何在vue2.0中配置webpack4.0】,对,就是这样的,我们手牵手从无到有在vue2.0
来配置起webpack4.0
,话不多说,走起!
基础构建
初始化环境依赖
首先我们新建一个项目webpack-vue-demo
,然后npm init
或npm init -y
初始化项目,会在根目录生成一个package.json
文件,打开package.json
瞅一眼,除了一些基础信息,啥也没有,别慌,没有就对了,这才称得上从无到有嘛。既然是在vue
中配置webpack
那项目肯定得要有vue
环境和webpack
环境,我们这里就都采用本地安装(安装依赖)的方式,通过两行命令来搞定:
npm i -S vue
npm i -D vue-loader vue-style-loader vue-template-compiler
- vue-loader
官方文档解释是vue-loader
是一个webpack
的loader
,它允许你以一种名为单文件组件 (SFCs)的格式撰写Vue
组件。这也就是vue
中可以.vue
文件的方式写组件的原因。vue-loader
会将.vue
的组件识别成三部分template
、script
、style
然后再通过webpack
配置中的其他相关loader
将其彻底解析成浏览器可识别的html
、js
、css
文件。 - vue-style-loader
用于处理vue-loader
解析后的style
。 - vue-template-compiler
把 vue-loader 提取出的 HTML 模版编译成对应的可执行的 JavaScript 代码。
npm i -D webpack webpack-cli
这里需要注意的是从webpack4.0
开始,webpack
和 cli
被分成了两个包,因此我们需要分别安装这两个依赖才可以,否则在控制台会输出提示安装webpack-cli
,当然缺少也是打包不成功的。
至此,我们的两个必要的环境依赖安装好了,下来我们将项目的基础目录和相关基础文件搞起来。
构建基础目录
项目根目录下创建src
文件夹,index.html
,webpack.config.js
或webpackfile.js
(webpack配置文件,所有的webapck配置都在这里进行),在src
下又分别创建index.js
, views
文件夹等项目所需文件,具体参考效果如下:
webpack-vue-demo(项目根目录)
—— src(项目源代码目录)
—— index.js(项目打包入口文件)
—— views(页面组件)
—— App.vue(项目根组件)
—— assets(图片资源目录,存放图片)
—— components(公共组件目录)
—— child.vue(子组件)
—— styles(公共样式目录,存放公共,全局等一些样式表)
—— index.html(html模板)
—— webpack.config.js/webpackfile.js(webpack配置文件)
—— package.json(包管理文件)
初始化vue(实例化,挂载等)
这部分没啥好说的,直接贴代码吧
<!--App.vue-->
<template>
<div id="app">
<Child></Child>
</div>
</template>
<script>
import Child from "@/components/child"; //这里可以使用@符号,是需要在webpack配置文件里面配置,后面会说到,先这样写。
export default {
name: "App",
data() {
return {};
},
components: {
Child
}
};
</script>
<style scoped>
</style>
<!--index.js-->
import Vue from 'vue'
import App from './views/App'
new Vue({
el:'#app',
render: h => h(App)
})
到此,项目基础工作已经基本落地完成,下来我们就来专注做配置的事情(这里项目还运行不起来,因为还没有webpack配置)。
配置 webpack(version-1)
在配置之前,我们先稍微补充点点额外的。
第一:我们在启动或者打包vue
项目的时候都是使用npm run dev
或npm run build
这样的命令来完成的,而这样的命令则是在package.json
里的scripts
中定义的。所以那到底这是为什么呢,为啥这里定义后就可以启动webpack
打包任务呢?
package.json
里面定义的scripts
字段(对象)是Npm Script
的一种表现形式,也就是说Npm Script
允许在package.json
文件里面使用scripts
字段定义任务,而Npm Script
本身就是Npm
内置的一个功能,专门用来执行任务的。所以在package.json
的scripts
对象里定义的每一个任务都是一个npm
可执行的任务。这些任务每一个对应一段 Shell 脚本,例如定义的dev
和build
, 其底层实现原理都是通过调用Shell
去运行脚本命令,执行npm run build
命令等同于执行命令node build.js
。又webpack
在执行打包压缩的时候是依赖nodejs
, so,应该明白了吧!执行Npm Script
任务就可以启动webpack
打包压缩程序。
第二:配置 Webpack
的方式有两种:
- 通过一个
JavaScript
文件描述配置,例如使用webpack.config.js
文件里的配置; - 执行
Webpack
可执行文件时通过命令行参数传入,例如webpack --devtool source-map
。
这两种方式可以相互搭配,例如执行 Webpack
时通过命令 webpack --config webpack.config.js
指定配置文件,再去 webpack.config.js
文件里描述部分配置。但是只通过命令行参数传入的选项,这种最为少见;顺势而为,我们该项目中会采用两种结合的方式。不过主要的配置都在webpack.config.js
文件里面进行。
下面就开始吧!
Entry
entry: 必填项,配置入口文件的名称,为string 类型。如果只有一个入口文件,则可以把它写成静态不变的,Webpack
执行构建的第一步将从入口开始搜寻及递归解析出所有入口依赖的模块。(执行打包压缩的入口)
<!--webpack.config.js-->
module.exports = {
entry: "./src/index.js"
}
Output
output:必填项,配置如何输出最终想要的代码的出口,是一个对象,常用的属性filename
(指定导出文件名)、path
(配置输出文件存放在本地的目录,必须是 string
类型的绝对路径。通常通过 Node.js
的 path
模块去获取绝对路径)
- Tip:在配置文件中可能会很频繁遇到path.resolve(__dirname, "xxx")的语法,这个语法是
node.js
中path
模块提供的一个绝对路径解析的方法,如果想要深入了解,可以去查看node.js
文档,我们这里只需知道它的作用就行。当然在使用的文件中需要手动在文件顶部require
进来才可以使用的。
<!--webpack.config.js-->
const path = require("path"); //node.js 里面的path模块,这里用来解析绝对路径的
module.exports = {
entry: "./src/index.js", //指定入口文件
output: {
filename: "[name].[hash].js", //导出的文件名,hash值是避免文件名缓存
path: path.resolve(__dirname, "dist") //导出的打包后文件输出路径(必须是绝对路径)
},
}
Loader
loader:必填项,模块转换器,可以理解为一个将非js模块翻译为js模块的具有文件转换功能的翻译员。因为webpack
在进行模块打包构建时只识别js
模块文件,那对于非js
的类型文件需要将其进行转换成js
类型,这就是我们项目中为啥可以正常使用图片,视频以及样式预处理器等的原因,它们都会对应有不同的loader
来对其进行翻译转换,当然这些loader
是需要配置才可以生效的。
- module:模块,
webpack
中一切皆模块(任何文件都看作是一个模块) - rules:配置模块的读取和解析规则,通常用来配置Loader。其类型是一个数组,数组里每一项都描述了如何去处理部分文件
- test、include、exclude:
text
(指定应用当前loader
的类型文件,这里就是所有.css
后缀的文件都应用css-loader来处理),include
(指定去查找的目录),exclude
(排除不需要查找的目录),一般include
和exclude
二选一结合test
使用。是缩小查询范围的一种优化手段。 - use: 配置应用的
loader
,可以是字符串、数组、对象 - loader:模块解析器,可以是字符串、数组、对象。
const path = require("path"); //node.js 里面的path模块,这里用来解析绝对路径的
module.exports = {
entry: "./src/index.js", //指定入口文件
output: {
filename: "[name].[hash].js", //打包导出文件的文件名
path: path.resolve(__dirname, "dist") //导出的打包后文件输出路径(必须是绝对路径)
},
module: {
rules: [
{
test: /\.css$/,//指定应用当前loader的类型文件,这里就是所有.css后缀的文件都应用css-loader来解析
use: [ "vue-style-loader", "css-loader"]
},
{
test: /\.scss/,
use: ["vue-style-loader","css-loader","sass-loader"]
},
{
test: /\.(png|jpg|gif|svg|bmp)$/,
use: {
loader: "url-loader",
options: {
esModule: false,
limit: 10 * 1024, //限制图片资源大小,小于10kb的图片会以 base64 编码输出,大于此限制值的会以拷贝方式(file-loader)放到 'outputPath'指定目录下
outputPath: "imgs/" //指定图片资源输出路径,不指定默认直接放到dist目录下,此时这里是 dist/imgs/
}
}
},
{
test: /\.js$/,
loader: "babel-loader",
exclude: /node_modules/ //不查找 'node_modules'目录
},
{
test: /\.vue$/,
use: "vue-loader"
}
]
}
};
关于
loader
,需特别注意 的是,若配置一组loader
,那么组内的loader
是有严格的执行顺序的,不可颠倒。顺序为按照数组索引反方向(从尾部往头部)依次执行,并将当前loader
解析结果传递给后一个loader
去解析,在最后一个loader
,返回 webpack 所预期的JavaScript
。
-
vue-style-loader
- 安装:
npm i -D vue-style-loader
- 描述:功能类似于
style-loader
,是将css-loader
加载后的css
作为样式标签动态注入到文档中,是专门应用于vue
模板环境下的样式表加载器。因此如果配置了vue-style-loader
就不需要再配置style-loader
了。
- 安装:
-
css-loader
- 安装:
npm i -D css-loader
- 描述:解释 @import 和 url() ,会 import/require() 后再解析它们。通俗的讲就是
css-loader
会找出当前css
文件中的@import
和url()
这样的导入语句,告诉Webpack
依赖这些资源,然后同时将当前css
文件 解析成模块,处理完后再把结果交给 style-loader 去处理。
- 安装:
-
sass-loader
- 安装:
npm i -D sass-loader
- 描述:sass-loader 的作用就是把
scss
源码转换为css
代码,再把css
代码交给css-loader
去处理。
- 安装:
-
url-loader
- 安装:
npm i -D url-loader
- 描述
- 可以把文件的内容经过
base64
编码后注入到JavaScript
(模板中或js中引入) 或者css
(css中引入) 中去,一般用来加载解析图片、视频等媒体资源,但通常是处理比较小的媒体资源,例如图片,将解析后的资源注入到代码中去,但因为是采用base64
编码后,因此会造成代码文件过大,所以,通常会配合limit
属性一起使用,当超过当前limit
限制,则采用file-loader
加载解析,将资源进行拷贝。这里还有两个属性值得注意,一般需要配合使用。 esModule
:默认为true
,表示文件加载器会生成使用ES
模块语法的JS
模块,如果关闭(false),则采用CommonJS
模块语法来生成JS
模块,这里一定要为false
,是踩坑发现的,如果不关闭,则 采用require
方式引入的模块资源打包后不能正常显示。outputPath
:指定图片资源输出路径,不指定默认直接放到dist目录下。
- 可以把文件的内容经过
- 安装:
-
babel-loader
- 安装:
npm i -D @babel/core @babel/plugin-transform-runtime @babel/preset-env babel-loader
- 描述
Babel
是一个JavaScript
编译器,能将采用ES6
或ES7
甚至更高规范的代码转为ES5
规范下的代码。为啥转换嘞,因为浏览器的支持性不好。那在项目使用过程中 通常采用配置loader
+ 插件 的形式来转换js
代码,这里的loader
也就是babel-loader
。需要注意下,因为babel-loader
执行比较耗时,因此使用exclude
去排除无需查找的目录,比如node_modules
,否则默认会查找所有目录下符合要求的文件。babel-plugin-transform-runtime
是Babel
官方提供的一个插件,作用是减少冗余代码。Babel
在把ES6
代码转换成ES5
代码时通常需要一些ES5
写的辅助函数来完成新语法的实现。babel-plugin-transform-runtime
的作用在于不把辅助函数内容注入到文件里。presets
属性告诉Babel
要转换的源码使用了哪些新的语法特性,一个Presets
对一组新语法特性提供支持,多个Presets
可以叠加。Presets
其实是一组Plugins
的集合,每一个Plugin
完成一个新语法的转换工作- 在
Babel
执行编译的过程中,会从项目根目录下的.babelrc
文件读取配置。.babelrc
是一个JSON
格式的文件,所以需要在项目根目录新建一个.babelrc
文件
<!--.babelrc--> { "presets": ["@babel/preset-env"],//设定转码规则 "plugins": ["@babel/plugin-transform-runtime"] // transform-runtime 插件表示不管浏览器是否支持ES6,只要是ES6的语法,它都会进行转码成ES5 }
- 安装:
-
vue-loader
- 安装:
npm i -D vue vue-loader vue-style-loader vue-template-compiler
Tip
:该loader
的安装往往会结合vue
一起安装。- 描述:文章开头已经描述,这里就不再重复说明。
- 安装:
至此,项目中常用到的 loader
就已经全部安装及说明完毕,可能心急的小伙伴已经迫不及待想试试看一下效果,但是,这会还真不行,还差一个重要的配置项 插件 (plugin),所以我们还得再往下继续看看。
Plugin
plugin:必填项 ,插件是 webpack
的支柱功能,用于扩展 Webpack
的能力,在 webpack
的构建流程中,plugin
用于处理更多其他的一些构建任务,只要是loader
无法实现的事,插件都可以完美的胜任。因此其地位和作用不言而喻,称得上是webpack
中最重要的配置。格式是数组,数组中的每一项都是用来行使不同目的的插件实例(new)。
const path = require("path"); //node.js 里面的path模块,这里用来解析绝对路径的
const HtmlWebpackPlugin = require("html-webpack-plugin"); //自动生成html
const VueLoaderPlugin = require("vue-loader/lib/plugin"); //必须导入此插件,它负责克隆您定义的任何其他规则,并将它们应用于.vue文件中的相应语言块
const MiniCssExtractPlugin = require("mini-css-extract-plugin"); //分离css
module.exports = {
...
plugins: [
new VueLoaderPlugin(),
new HtmlWebpackPlugin({
template: "./index.html", //模板文件
filename: "index.html", //文件名
hash: true //避免缓存
}),
new MiniCssExtractPlugin({
filename: "styles/[name].[hash].css", //指定分离生成的css文件名,hash为了避免缓存
})
]
};
- vue-loader-plugin
- 安装:在安装
vue-loader
的时候会生成 - 描述:将你定义过的其它规则复制并应用到
.vue
文件里相应语言的块。例如,如果你有一条匹配/\.js$/
的规则,那么它会应用到.vue
文件里的<script>
块。
- 安装:在安装
- html-webpack-plugin
- 安装:
npm install -D html-webpack-plugin
- 描述:该插件会自动生成一个
HTML5
文件, 其中包括使用script
标签的body
中的所有webpack
包,因此我们无需担心打包后的所有依赖,它会帮我们自动引入html
模板中,例如(js,css),解放了双手。- template: 这里需要我们提前定义好一个
html
模板文件,template
属性就是用来指定所使用的模板文件 - filename: 是指定产出后的文件名,就是
dist
目录下的那个html
文件名。 - hash:避免文件缓存
- template: 这里需要我们提前定义好一个
- 安装:
- mini-css-extract-plugin
- 安装:
npm install -D mini-css-extract-plugin
- 描述:
- 该插件主要作用用来分离
css
代码,我们的css
代码在经过css-loader,style-loder
解析后以字符串的形式存在于js文件中。这样随着项目的业务扩展,会导致当前js文件会越来越大,并且也会加载的很慢,所以我们这里使用mini-css-extract-plugin
来将每一个js
文件中的css
代码单独分离出来,并且支持异步、按需加载。 - 该插件的配置方式跟其余插件略有不同,除了在
plugins
数组里注册外,还需要将style-loader
或vue-style-loader
替换成如下的写法:<!--webpack.config.js--> module: { rules: [ { ... use: [ { loader: MiniCssExtractPlugin.loader //分离css }, "css-loader" ] }, { ... use: [ { loader: MiniCssExtractPlugin.loader }, "css-loader", "sass-loader" ] }, ] }
- 该插件主要作用用来分离
- 安装:
到这里,项目就可以进行打包了。只不过我们需要在 package.json
的 script
属性中定义下任务命令就好了。
<!--package.json-->
...
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "webpack --mode development",//开发环境下打包命令
"build": "webpack --mode production"//生产环境下打包命令
},
ok,控制台运行命令 npm run dev
或 npm run build
会发现在项目根目录产生一个 dist
文件夹,dist
文件夹下就是 webpack
打包后的源代码,我们可以编辑器打开 index.html
瞅一眼会发现多了一个 <link>
和 <script>
标签,这就是上面提到的 html-webpack-plugin
插件帮我们完成的。然后浏览器运行 index.html
文件,会发现有内容,并且正是我们开始在child.vue
组件里定义的东西。此时就说明打包已经成功。
也许,此时的你正沉浸在喜悦中无法自拔,可是,这并不是我们想要的结果。试想下 vue-cli
中打包项目的时候是如何的一个情景,并且当我们更改代码的时候的热更新又是如何的一个情景,所以,还需要优化。首先先整理下需要实现的几个效果
- 本地可以运行项目,支持代码热更新、热替换
- 项目运行或者打包可以看到进度条。
好了,明确需求后,我们就来实现它。还是先贴出代码,再叙述实现吧。
<!--webpack.config.js-->
...
const webpack = require("webpack");
const ProgressBarPlugin = require("progress-bar-webpack-plugin") //运行/打包,显示进度条
module.exports = {
...
devServer: {
host: 'localhost',//开发服务器监听的主机地址
port: 8000, //开发服务器监听的端口号,默认是 8080
compress: true, //启用压缩
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new ProgressBarPlugin()
]
};
-
webpack-dev-server
-
安装:
npm i -D webpack-dev-server
-
描述:
- 使用
DevServer
会帮我们在本地启动一个服务,这样我们可以通过在浏览器访问服务地址来预览效果,而不用每次手动去打开index.html
文件。 DevServer
它提供了一些配置项可以改变DevServer
的默认行为。 要配置DevServer
,除了在配置文件里通过devServer
传入参数外,还可以通过命令行参数传入。 注意只有在通过DevServer
去启动Webpack
时配置文件里devServer
才会生效,因为这些参数所对应的功能都是DevServer
提供的,Webpack
本身并不认识devServer
配置项。
<!--webpack.config.js--> module.exports = { ... devServer: { host: 'localhost',//开发服务器监听的主机地址 port: 8000, //开发服务器监听的端口号,默认是 8080 compress: true, //启用压缩 } };
如果使用了命令行参数,则启动服务时会将参数写入
devServer
配置中,如果有重名,则命令行参数会覆盖配置项属性。DevServer
使用需要在package.json
里的script
属性中配置命令:
<!--package.json--> "scripts": { "dev": "webpack-dev-server --open", },
webpack-dev-server
命令启动服务后运行的打包文件是在 内存中,并不在 硬盘中,为了验证这一点,你可以将dist
文件夹删掉,然后重启服务,会发现并不会在项目根目录生成dist
文件夹,况且项目仍然可以运行。
- 使用
-
-
HotModuleReplacementPlugin
- 安装:
webpack
内置的插件,因此无需单独安装。 - 描述: 该插件是用来启用热替换模块(HMR)的,启用热替换模块的好处是当我们更改了模块文件的代码时浏览器在不刷新当前页面的情况下更新页面内容。其实实现有两种方式,除了这里的使用插件,还要就是使用命令行
webpack-dev-server --hot
,两者看心情任选其一即可。
- 安装:
-
progress-bar-webpack-plugin
- 安装:
npm i -D progress-bar-webpack-plugin
- 描述:该插件比较简单,就是一个用来显示打包进度的插件,尤其是当项目比较大的时候,打包比较耗时,显示进度会显得体验比较友好。
- 安装:
那麽现在,我们再npm run dev
的时候就会在本地使用服务来运行当前项目,当修改模块中的代码,会自动热更新。而且还会有进度条,这样看起来就舒服多了吧。
Resolve
resolve:可选项,格式是对象,配置 Webpack
如何寻找模块所对应的文件。 Webpack
内置 JavaScript
模块化语法解析功能,默认会采用模块化标准里约定好的规则去寻找,但你也可以根据自己的需要修改默认的规则。修改的规则就要定义在 resolve
中,以下列出来几个比较常见的解析规则
<!--webpack.config.js-->
...
module.exports = {
...
resolve: {
extensions: [".js", ".vue", ".scss", ".css"], //后缀名自动补全,当导入文件的时候可以省略后缀名不写
alias: {
vue$: "vue/dist/vue.esm.js", //精确匹配,当import Vue from 'vue'的时候引入的是vue.esm.js这个版本库而不是其他版本库
"@": path.resolve(__dirname, "../src"), //用@代替./src路径 所以就可以 import xx from ' @/xx'
}
}
}
到现在,其实关于 vue2.0
中配置webpack4.0
的常用配置的知识点差不多已经说完了。那麽是时候将 webpack.config.js
的整体代码 bia
出来了。
<!--webpack.config.js-->
const path = require("path"); //node.js 里面的path模块,这里用来解析绝对路径的
const webpack = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin"); //自动生成html
const VueLoaderPlugin = require("vue-loader/lib/plugin"); //必须导入此插件,它负责克隆您定义的任何其他规则,并将它们应用于.vue文件中的相应语言块
const MiniCssExtractPlugin = require("mini-css-extract-plugin"); //分离css
const ProgressBarPlugin = require("progress-bar-webpack-plugin") //运行/打包,显示进度条
module.exports = {
entry: "./src/index.js", //指定入口文件
output: {
filename: "[name].[hash].js", //导出的文件名
path: path.resolve(__dirname, "dist") //导出的打包后文件输出路径(必须是绝对路径)
},
resolve: {
extensions: [".js", ".vue", ".scss", ".css"], //后缀名自动补全,当导入文件的时候可以省略后缀名不写
alias: {
'vue$': 'vue/dist/vue.esm.js',//精确匹配,当import Vue from 'vue'的时候引入的是vue.esm.js这个版本库而不是其他版本
"@": path.resolve(__dirname, "./src") //用@代替./src路径 所以就可以 import xx from ' @/xx'
}
},
module: {
rules: [
{
test: /\.css$/,//指定应用当前loader的类型文件,这里就是所有.css后缀的文件都应用css-loader来处理
use: [
{
loader: MiniCssExtractPlugin.loader //分离css
},
"css-loader"
]
},
{
test: /\.scss/,
use: [
{
loader: MiniCssExtractPlugin.loader
},
"css-loader",
"sass-loader"
]
},
{
test: /\.(png|jpg|gif|svg|bmp)$/,
use: {
loader: "url-loader",
options: {
esModule: false,
limit: 10* 1024, //限制图片资源大小,小于10kb的图片会以 base64 编码输出,大于10kb的会以拷贝方式(file-loader)放到 'outputPath'指定目录下
outputPath: "imgs/" //指定图片资源输出路径,不指定默认直接放到dist目录下,此时这里是 dist/imgs/
}
}
},
{
test: /\.js$/,
loader: "babel-loader",
exclude: /node_modules/ //不查找 'node_modules'目录
},
{
test: /\.vue$/,
use: "vue-loader"
}
]
},
devServer: {
host: 'localhost',//开发服务器监听的主机地址
port: 8000, //开发服务器监听的端口号,默认是 8080
compress: true, //启用压缩
},
plugins: [
new VueLoaderPlugin(),
new webpack.HotModuleReplacementPlugin(),
new HtmlWebpackPlugin({
template: "./index.html", //模板文件
filename: "index.html", //文件名
hash: true //避免缓存
}),
new MiniCssExtractPlugin({
filename: "styles/[name].[hash].css",
}),
new ProgressBarPlugin()
],
devtool: "source-map" //可以直接在浏览器控制台source下查看项目未打包的源代码,在出现一些错误的时候,
//如果不使用source-map的时候,错误无法定位到源代码中。
//使用了source-map以后,可以直接定位到错误出现的行
};
同时也附上仓库源代码地址,有需要可以直接 fork
vue2.0中配置webpack4.0版本1源代码地址
以上为版本1,难道还有版本2不成(黑人问号脸)?,对,确实还有版本2。卧槽,无情!
在实际开发中我们往往会有不同的环境,常见的就是开发环境和生产环境,根据不同的环境,往往我们的webpack
配置是有差异的,因此就需要把不同环境的配置从 webpack.config.js
文件中分离出来。如何分离,请继续往下看。
webpack 分环境配置(version-2)
新建配置目录
项目根目录新建 build
文件夹,build
目录下新建三个配置文件,分别是:webpack.base.conf.js
(基础配置文件)、webpack.dev.conf.js
(开发环境配置文件)、webpack.pro.conf.js
(生产环境配置文件)。
分离配置
1. webpack.base.conf.js
webpack.base.conf.js
文件放置开发环境和生产环境webpack
打包时候需要的公共基础配置项。
<!--webpack.base.conf.js->
const path = require("path"); //node.js 里面的path模块,用于生成绝对路径
const VueLoaderPlugin = require("vue-loader/lib/plugin"); //必须导入此插件,它负责克隆定义的任何其他规则,并将它们应用于.vue文件中的相应语言块
const CopyPlugin = require("copy-webpack-plugin");//拷贝静态文件,例如.txt,.md等文件
const MiniCssExtractPlugin = require("mini-css-extract-plugin");//分离css
const ProgressBarPlugin = require("progress-bar-webpack-plugin"); //运行/打包,显示进度条
module.exports = {
entry: path.resolve(__dirname, "../src/index.js"), //指定入口文件
output: {
filename: "[name].[hash].js", //导出的文件名
path: path.resolve(__dirname, "../dist") //导出的打包后文件输出路径(必须是绝对路径)
},
resolve: {
extensions: [".js", ".vue", ".scss", ".css"], //后缀名自动补全,当导入文件的时候可以省略后缀名不写
alias: {
vue$: "vue/dist/vue.esm.js", //精确匹配,当import Vue from 'vue'的时候引入的是vue.esm.js这个版本库而不是其他版本
"@": path.resolve(__dirname, "../src"), //用@代替./src路径 所以就可以 import xx from ' @/xx'
assets: path.resolve(__dirname, "../src/assets")
}
},
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader
},
"css-loader"
]
},
{
test: /\.scss/,
use: [
{
loader: MiniCssExtractPlugin.loader
},
"css-loader",
"sass-loader"
]
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
use: {
loader: "url-loader",
options: {
esModule: false,
limit: 10 * 1024, //限制图片资源大小,小于10kb的图片会以 base64 编码输出,大于的会以拷贝方式(file-loader)放到 'outputPath'指定目录下
outputPath: "static/imgs/" //指定图片资源输入路径,不指定默认直接放到dist目录下,此时这里是 dist/static/imgs/
}
}
},
{
test: /\.js$/,
loader: "babel-loader",
exclude: /node_modules/ //不查找 'node_modules'目录
},
{
test: /\.vue$/,
use: "vue-loader"
}
]
},
plugins: [
new VueLoaderPlugin(),
new MiniCssExtractPlugin({
filename: "static/css/[name].[hash].css"
}),
new ProgressBarPlugin(),
new CopyPlugin([
{
from: path.resolve(__dirname, "../src/static"),
to: "static"
}
])
]
};
- copy-webpack-plugin
- 安装:
npm run copy-webpack-plugin -D
- 描述:
- 这里新增了一个插件,
copy-webpack-plugin
,就是将既不是js
,也不是css
,图片
之类的静态文件,比如README.md
,也希望能打包到我的项目里,而这个插件就是采用拷贝的方式来将其复制进我们的打包目录。 - from:需要拷贝的静态文件源路径
- to:文件拷贝后输出的目标位置。
- 这里新增了一个插件,
- 安装:
2. webpack.dev.conf.js
webpack.dev.conf.js
文件仅存放开发环境下 webpack
打包时候/运行项目的 webpack
配置项。依然先 bia 代码,再进行说明。
const path = require("path");
const merge = require("webpack-merge");//合并配置项的方法
const base = require("./webpack.base.conf");//基础配置项
const webpack = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin"); //自动生成html
const FriendlyErrorsPlugin = require("friendly-errors-webpack-plugin"); //可以识别某些类的webpack错误,并清除,汇总并确定优先级。
const devWebpackConfig = merge(base, {
mode: "development",
devtool: "source-map",
devServer: {
host: "localhost", //用于配置 DevServer 服务监听的地址,想要局域网中的其它设备访问你本地的服务,请配置为 0.0.0.0,默认只有本地可以访问
port: 8000, //访问端口号,默认8080,如果被占用,会自动更换
quiet: true, // necessary for FriendlyErrorsPlugin
compress: true, //启用压缩
open: false //自动打开浏览器
},
plugins: [
new webpack.HotModuleReplacementPlugin(), //模块热替换,当更新代码时候自动编译,无需手动更新,一般配合webpack-dev-server 使用
new HtmlWebpackPlugin({
template: "./index.html", //模板文件
filename: "index.html", //文件名
inject: true // true || 'head' || 'body' || false,注入资源到给定的html模板文件,如果为true或者body,则将所有js文件都将放置在body元素的底部
})
],
devtool: "source-map" //在浏览器端调试方便,可以直接看源码
});
module.exports = new Promise(resolve => {
const host = devWebpackConfig.devServer.host;
const port = devWebpackConfig.devServer.port;
devWebpackConfig.plugins.push(
new FriendlyErrorsPlugin({
compilationSuccessInfo: {
messages: [`Your application is running here: http://${host}:${port}`]
},
onErrors: function(severity, errors) {
// You can listen to errors transformed and prioritized by the plugin
// severity can be 'error' or 'warning'
}
})
);
resolve(devWebpackConfig);
});
-
webpack-merge
- 安装:
webpack
内置,因此无需单独安装。 - 描述:
webpack-merge
是webpack
提供的一个可以合并对象/数组并生成新的对象的方法。因此我们这里可以借助该方法,将webpack.base.conf.js
暴露的基础配置对象合并进来。
- 安装:
-
friendly-errors-webpack-plugin
- 安装:
npm i -D friendly-errors-webpack-plugin
- 描述:
-
可以识别某些类的webpack错误,并清除,汇总并确定优先级。简单讲,就是一个捕获并收集打包编译过程中发生的错误,并给出提示的插件。这里我们用它来在编辑器控制台显示当前项目在浏览器端的访问地址(vue-cli中那样)
例如:
-
配置该插件时候需要注意两点:
- 为了引用到当前文件中配置的主机号和端口号,因此需要改写下
module.exports
导出配置的写法,这里我们使用导出Promise
对象,具体使用请看上方的代码。或者参考官方文档。 - 除了需要在
plugins
里注册实例,还需在devServer
里面添加quiet: true
,固定用法。
- 为了引用到当前文件中配置的主机号和端口号,因此需要改写下
-
- 安装:
3. webpack.pro.conf.js
webpack.pro.conf.js
文件仅存放生产环境下 webpack
打包时候的 webpack
配置项。依然先 bia 代码,再进行说明。
const path = require("path");
const merge = require("webpack-merge"); //合并webpack options
const base = require("./webpack.base.conf");
const HtmlWebpackPlugin = require("html-webpack-plugin"); //自动生成html
const TerserPlugin = require("terser-webpack-plugin"); //压缩js
const OptimizeCSSPlugin = require("optimize-css-assets-webpack-plugin");//压缩css
const { CleanWebpackPlugin } = require("clean-webpack-plugin"); //每次打包前,先清理掉之前的打包文件
module.exports = merge(base, {
mode: "production",
optimization: {
minimize: true,
minimizer: [new TerserPlugin()],
},
plugins: [
new HtmlWebpackPlugin({
template: "./index.html", //模板文件
filename: "index.html", //文件名
inject: true, // true || 'head' || 'body' || false,注入资源到给定的html模板文件,如果为true或者body,则将所有js文件都将放置在body元素的底部
favicon: path.resolve(__dirname,'../favicon.ico'),
//如果将minify选项设置为true(当webpack的模式为“生产”时为默认值),则将以下选项来缩小生成的HTML(压缩html资源)
minify: {
removeComments: true, //移除注释
collapseWhitespace: true, //合并空格
removeAttributeQuotes: true //移除属性双引号
}
}),
new OptimizeCSSPlugin({
assetNameRegExp: /\.css$/g,
cssProcessor: require("cssnano")
}),
new CleanWebpackPlugin()
]
});
-
terser-webpack-plugin
-
安装:
npm i -D terser-webpack-plugin
-
描述:
- 该插件用来压缩
js
代码,使用它而舍弃uglifyjs-webpack-plugin
插件的最大一个原因就是支持es6
语法,而 ``uglifyjs-webpack-plugin`不支持,对就是这么任性。 - 该插件的配置方式有点特别,不是注册在
plugins
中,而是在optimization
中,关于optimization
,看官方文档的描述为优化,是一个对象,然后对象里面可以手动配置重写一些优化项和策略。感觉比较高深,我就浅尝辄止,将TerserPlugin
插件相关的优化项写进来。
<!--webpack.pro.conf.js--> optimization: { minimize: true, //告知 webpack 使用 TerserPlugin 压缩 打包后的js文件 minimizer: [new TerserPlugin()], //允许通过提供一个或多个定制过的 TerserPlugin 实例,覆盖默认压缩工具(minimizer)。 },
- 该插件用来压缩
-
-
optimize-css-assets-webpack-plugin
- 安装:
npm i -D optimize-css-assets-webpack-plugin
- 描述:
- 优化/压缩 css 的插件,使用该插件不仅压缩出来的 css 拥有很好的格式,而且压缩过程中采用的多种优化策略来保证 css 文件体积尽量的小
- assetNameRegExp:指定要压缩优化那种类型的静态资源文件(正则表达式)
- cssProcessor:指定压缩优化
css
文件时采用的那种css
处理器,默认为cssnano
- 安装:
-
clean-webpack-plugin
- 安装:
npm i -D clean-webpack-plugin
- 描述:
- 该插件用于删除/清理构建文件夹(dist),可以对比下该插件使用前后
dist
目录下文件差异,会发现安装前多次打包后dist
目录下会保留每次打包生成的构建文件,那这样就带来一个问题,随着我们打包次数的增加,若不手动删除dist会越来越大。这肯定不是我们想要的。因此使用该插件可以帮我们每一次重新打包前删除先前的构建文件夹。 - 该插件的引入略有点特殊
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
,固定用法,了解即可。
- 该插件用于删除/清理构建文件夹(dist),可以对比下该插件使用前后
- 安装:
还记得我们 package.json
script
属性里面的任务命令吗?对,这里现在得更改下就可以起飞了。
<!--package.json-->
...
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "webpack-dev-server --config ./build/webpack.dev.conf.js",
"build": "webpack --config ./build/webpack.pro.conf.js"
},
...
npm run dev
和 npm run build
操作起来,看看此时构建过程跟构建后的文件跟之前有啥不同呢? 嘿嘿嘿!。
相信能坚持看到这里的老铁绝对是真爱,所以如果您觉得对你有帮助或者内心有些许波澜,麻烦给小弟 点个赞 或 star~下,蟹蟹!
最后附上版本2的仓库源代码地址,有需要可以直接 fork
vue2.0中配置webpack4.0版本2源代码地址
后记
以上就是在 vue2.0
中从 0 - 1
配置 webpack
的全部内容了,webpack4.0
的东西非常之多,也非常之高深,作为一个前端菜鸟深知需要学习和进步的空间还很大,因此,如若有 不恰当/不准确 之处,还望路过的各位大佬多多指教。不胜感激!