看完你就会用 webpack 了
终极目标
可以使用 webpack 打包 vue 项目。
总体计划
- webpack 安装和简单使用
- 通过配置文件增加打包的功能
- 学习各种loader可以让webpack去打包各种文件
- 学习 plugins强大webpack 的功能
- 学会配置 webpack-dev-server 可以在开发过程中实时更新预览代码
- 配置webpack 实现 .vue 文件的打包
webpack-安装基本使用
学习目标
- 明白 webpack 的作用。
- 掌握 webpack 的基本使用。
- 解决项目中代码打包的问题。(通过 webpack 对代码进行打包)
学习计划
- webpack的用处。
- webpack 的安装环境
- webpack 的安装
- 代码文件结构
- 如何改造普通代码文件为模块化,便于 webpack 打包
- 使用 简单命令预览 webpack 打包效果
- 查看打包后的 js 并简单介绍下 webpack 打包依据。
- 通过 es6 模块化文件使用 webpack 打包
- 总结
开始学习
webpack 的世界 一切皆模块
1. webpack 的作用(打包)
webpack 把模块收集梳理打包
- 对我们开发的项目进行打包(编译,把我们的代码转换成浏览器可以编译的代码,例如 es6 转 es5,scss 转 css ,css 增加前缀,把.vue 拆分成.js和.css)
- 开发过程中时时编译
- 通过 webpack server 生成一个临时的本地服务,对我们开发的项目的代码进行时时编译。
- 项目开发完毕对资源进行打包
- 压缩
- 不压缩
- 开发过程中时时编译
2. 安装 webpack
webpack中文网
1. 安装环境
安装 node,目前安装 node 会自动安装 npm。
node 中文网
创建一个文件夹。例如 demo1
使用 npm 命令初始化 node 环境。
npm init -y
这样会产生一个 package.json 文件
{
"name": "demo1",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
2. 安装webpack
1.在命令行工具中输入(推荐局部安装)
npm i webpack webpack-cli -D
当看到命令行中出现如下代码,代表安装成功了。
+ webpack-cli@3.3.12+ webpack@4.43.0
added 391 packages from 218 contributors in56.033s
"devDependencies": {"webpack": "^4.43.0",
"webpack-cli": "^3.3.12"
}
i 是 install 的简写
-D 是--save-dev的简写,其包名称及版本号会存在 package.json 的 devDependencies 这个里面,而--save则会将包名称及版本号放在 dependencies 里面。
延伸:dependencies是运行时依赖,devDependencies是开发时的依赖 (这里大家知道就可以了,以后的课程会终点介绍)
webpack 4x以上,webpack将命令相关的内容都放到了webpack-cli,所以还需要安装webpack-cli。
注意:
webpack 和 webpack-cli 推荐同时安装,这样可以保证webpack-cli 对应 当前安装的 webpack。
项目名称不要叫 webpack 会导致安装失败。
如何查看版本号?由于webpack 不是全局安装 查看版本不能使用
webpack -v
而是使用
node_modules\.bin\webpack -v
// 4.43.0
或者
npx webpack -v
// 4.43.0
者来检测版本,注意这里npm版本号要求 5.2 之后。
npx webpack
等价于 node_modules\.bin\webpack
3. 创建基本文件代码
环境准备完成之后我们开始创建几个基本文件,其目录结构如下:
deomo1/root|-index.html
|-index.js
|-package.json
|-tool.js
index.html 代码
<!DOCTYPE html><htmllang="en">
<head>
<metacharset="UTF-8">
<metaname="viewport"content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<divid="app"></div>
</body>
<scriptsrc="https://juejin.im/post/5f14f886f265da2306247f7b/tool.js"></script>
<scriptsrc="https://juejin.im/post/index.js"></script>
</html>
tool.js 代码
const updateDom = (id, content) =>{window.document.getElementById(id).innerHTML = content
}
index.js 代码
updateDom('app','传智播客')
痛点
index.js 依赖 tool.js 所以 index.html 中文件不可以换位置
多人开发项目时候无法保证变量是否唯一性(变量冲突)。例如两个文件中分别存在 tool.js var a = 100;index.js var a =1000;
低版本浏览器不识别 ES6 语法。
代码没有经过混淆存在安全隐患,例如别人可以通过你的代码推断出服务器接口请求的一些参数。
随着 js 文件个数增加,增加了项目管理的难度,例如各个js 文件依赖,变量等等
解决方案
通过使用 webpback 把多个 js 文件打包成一个。
4. 修改基本文件代码为模块化写法
本代码实例为 CommonJS 模块化写法,具体改造如下
tool.js
const updateDom = (id, content) =>{window.document.getElementById(id).innerHTML = content
}
// nodejs中的模块
module.exports = {
updateDom
}
index.js
const {updateDom} = require('./tool');updateDom('app','传智播客')
改完之后的代码我们再次直接通过浏览器打开发现浏览器报错,因为浏览器不能识别。接下来通过 webpack 对我们的diamond进行打包操作。
注意
在 webpack 4 中,可以无须任何配置就可以使用。
简单的打包操作
npx webpack index.js //入口文件
npx
解释见上文结果
Hash: c4b4044439973defe187
Version: webpack 4.43.0
Time: 425ms
Builtat: 2020-07-16 4:51:35 PM
AssetSizeChunksChunkNames
main.js 1.05 KiB 0 [emitted] main
Entrypointmain = main.js
[0] ./index.js 71 bytes {0} [built]
[1] ./tool.js 160 bytes {0} [built]
同时根目录生成了一个叫做 dist 的文件夹里面存在一个
main.js
的文件。同时有一段黄色的警告,因为我们没有告诉 webpack 我们的需要打包的模式是开发模式(我理解为开发代码阶段)还是生产模式(我一般理解为打包上线)。
5 打包后的 js
main.js
就是 index.js
和 tool.js
两个文件打包后的结果。
基本原理 webpack 会分析入口文件中的引用关系把相关的文件合并到一起,例如:
如果 index.js 中没有引用 tool.js 那么打包的 main.js 就没有tool.js 的代码。
(简单给学生看下mian.js)
6. 引入打包后的js
修改 index.html
<!DOCTYPE html><htmllang="en">
<head>
<metacharset="UTF-8">
<metaname="viewport"content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<divid="app"></div>
</body>
<scriptsrc="./dist/main.js"></script>
</html>
7. 使用 ES6 的模块化导出
创建一个 tooles6.js 文件
const log = (content) => {console.log(Date.now(), content)
}
// es6 模块化导出
export { log }
在 index.js 文件中引入
// node 模块化导入const {updateDom} = require('./tool');
// es6 模块化导入
import {log} from'./tooles6';
updateDom('app','传智播客')
log('测试webpack是否能识别es6的模块化')
小结
- webpack 自动识别各种依赖处理打包文件
- webpack 通过入口文件
- webpack 可以用来打包多个或一个 js 文件(多个合成一个)
- 优点:不必去关心它们的依赖
- 基于 node.js 不建议全局安装,直接通过
-D
安装到项目即可。 - 每次打包都会生成新的文件,如果有同样名字的会覆盖
- 支持两种模块化
- commonjs
- es6
webpack-基本配置
学习目标
我们如何配置webpack 来满足我们的需求?
我们如何简化 webpack 的命令,可以快速使用
我们如何自定义打包入口和出口路径?
通过下面的课程我们可以掌握webpack 的基本配置满足我们项目打包的基本需求。
学习计划
- 创建默认配置文件 webpack.config.js
- 指定配置文件进行打包操作
- 通过package.json 进行简化 webpack 的命令
- 自定义打包文件和输出文件位置及名称
- 总结
开始学习
在 webpack 4 中,可以无须任何配置使用,然而大多数项目会需要很复杂的设置,这就是为什么 webpack 仍然要支持 配置文件。这比在终端(terminal)中手动输入大量命令要高效的多,所以让我们创建一个配置文件,取代我们之前使用 cli 命令执行的方式。
来自官网的一段话
webpack 在工作时,它会默认去根目录下找一个名为 webpback.config.js 的文件(如果找不到,则它会用一些默认设置)。
webpback.config.js 就是webpack的配置文件,在这个配置文件中,我们可以通过一个 导出一个 json对象去配置webpback的参数,让打包更加灵活。
1. 创建默认配置文件 webpack.config.js
位置
我们先指定一下打包模式 mode
module.exports = {mode: "development"// production(生产)
}
接下来再次运行打包命令,查看产生的main.js文件的内容,对比与之间的变化。
- 黄色警告没有了,因为我们已经设置了 mode。
- 我们可以把 webpack 的配置文件想象成 webpack 是一个函数,它接受一个对象,通过对象来让 webapck 函数来产生我们想要的结果。
此文件的意义是导出一个配置项:用来配置 webpack 如何打包。
在操作层面,就是学习如何去使用这个文件。
mode模式:
- development:开发模式(代码不会压缩 混淆)
- production:生产模式(压缩,混淆,加密....... 不可读)
2. 指定配置文件(自定义配置文件名)
目的
为了实现多种打包模式,例如开发模式,生产模式,我们可以写在一个配置文件中但是它不利于维护。
我推荐把不同功能的配置文件单独分开写,通常工作中也是这样的。
在默认情况下,webpack会找一个名为 webpack.config.js的文件作为它的配置文件,但是,针对不同的场景,我们可以自行决采用哪个配置文件,换句话说,配置文件不一定必须叫webpack.config.js
。
下面,自已创建一个webpack.dev.js的文件用它来做配置文件,并使用它进行打包
1. 在根目录下创建自定义配置文件
在项目根目录下创建webpack.dev.js
,内容如下:
module.exports = {mode: 'development',
output:{
filename:'bundle.js'
}
}
2. 使用这个文件进行打包的配置
基本格式
npx webpack --config webpack的配置文件 入口文件
运行命令
npx webpack --config webpack.dev.js index.js
3. 通过 package.json 中的 scripts 简化运行命令
基本格式
"scripts": {"自定义命令名": "要具体执行的代码",
}
示例
"scripts": {"build": "webpack --config webpack.dev.js index.js"
}
运行命令
npm run build//相当于是 npx webpack --config webpack.dev.js index.js
4. 设置打包入口文件和出口路径
在webpack中:
- 默认入口是:./src/index.js
- 默认出口是:./dist/main.js。
1. 设置入口路径
我们在实际工作中入口文件往往不是 index.js 也许叫 app.js
调整目录结构
|-package.json|-index.html
|-src/
|-src/js
|-------app.js
|-------tool.js
|-------tooles6.js
修改src/index.js的名字为src/js/app.js
在webpack.config.js的配置项中添加
entry
,如下module.exports = {
mode: 'development', // 打包方式
entry:'./src/js/app.js'// 入口文件
}
修改快速打包命令
"scripts": {
"build": "webpack"
}
因为我们使用的是 webpack.config.js 所有这里不需要使用
--config webpack.config.js
去指定配置文件。
重新打包测试
npm run build
2. 设置出口路径
在webpack.config.js的配置项中添加
output
,如下// 引入nodejs中的核心模块
const path = require('path')
console.log(path.join(__dirname,'/build'))
module.exports = {
mode: "production",
entry: './src/js/app.js', // 入口文件
output: {
"path": path.join(__dirname,'/build'), // 决定出口文件在哪里
"filename": "bundle.js"// 设置出口文件的名字。默认情况下,它叫main.js
}
}
说明:
- output中的filename用来指定打包后的文件名字。
- output中的path用来指定打包后的路径。注意:它必须是绝对路径。所以,这里引用path模块中的resolve方法来生成绝对路径。
- 如果path中的路径不存在,它会自动创建一个默认的路径名称
dist
。
重新打包测试
npm run build
小结
- webpack的配置文件默认名是webpack.config.js
- 也可以单独指定 webpack 的配置文件来满足多种场景的需要。
- 学习webpack就学习webpack.config.js的使用。
- 把webpack的打包命令集成到script中可以简化打包命令,同时方便其他合作人员的使用。
- 自行定义入口和出口文件
灵魂三问
有什么用?
打包
为什么用它?
工程化:前端任务重需要有工具来管理
开发、上线
怎么用?
学习 webpack.config.js 不用记住,多看文档,仅仅需要记住最外面基本配置作用即可。
webpack-高级配置
1. loader
介绍
为什么用 loader?
webpack 在不使用loader的时候仅仅可以处理 .js 格式的文件,而我们项目中有着各种格式的文件,以及需要对 js文件进行进一步处理例如 es6 转 es5。
1.目的
通过loader
对要打包的文件进行语法转化。
2.作用
将一个个文件以字符串的形式读入,对其进行语法分析及进行转换。
3.原理
可以把 loader
理解成一个翻译员,把源文件经过转换后输出结果,并且一个文件还可以链式的多次翻译。
loader
也是一个模块,默认导出为一个 node 形式的函数,这个函数在 loader
进行资源转换时候调用,并通过 this上下文访问。
module.exports = function(source) {// source 为 compiler 传递给 Loader 的一个文件的原内容
// 该函数需要返回处理后的内容,这里简单起见,直接把原内容返回了,相当于该`Loader`没有做任何转换
return source;
};
转换:一个Loader
的职责是单一的,只需要完成一种转换。 如果一个源文件需要经历多步转换才能正常使用,就通过多个Loader
去转换。 在调用多个Loader
去转换一个文件时,每个Loader
会链式的顺序执行, 第一个Loader将会拿到需处理的原内容,上一个Loader
处理后的结果会传给下一个接着处理,最后的Loader
将处理后的最终结果返回给Webpack。
所以,在你开发一个Loader
时,请保持其职责的单一性,你只需关心输入和输出。
实例
1. 使用 css-loader ,style-loader 处理文件中的 .css 文件
准备
public.css
body,html{padding:0;
font-size:14px;
}
style.css
@import"public.css";div {
border:4px solid #ccc;
width: 50%;
height: 200px;
margin:30px auto;
box-shadow: 3px3px3px#ccc;
background-color: #fff;
text-align: center;
}
app.js 增加引入 css 文件
// node 模块化导入const {updateDom} = require('./tool');
// es6 模块化导入
import {log} from'./tooles6';
// + 新增 css 文件引入
import'./../css/style';
updateDom('app','传智播客')
log('测试webpack是否能识别es6的模块化')
使用 webpack 打包
npm run bulid
此时控制台
我们看到控制台报错,这里我们只需要注意 关键子 loader 以及文件格式.css ,由此可以推断出是缺少 css-loader
css-loader
安装
npm install css-loader -D
-D devDependencies是开发时的依赖
css-loader
在webpack中配置
module.exports = {module: {
rules: [
{
test: /\.css$/,
use: ['css-loader']
},
],
}
}
在 expors 的对象内部增加 module 对象 通过配置 rules 数组进行 loader 的配置
执行顺序 :从数组的最末端开始执行,也可以简单的理解为从右往左。
执行命令及结果
此时打开浏览器观看 样式并没有生效 css-loader 的作用就是帮助 webpack 读取 .css 文件,并打包进 bundle.js中,此时还需要 style-loader
安装
npm i style-loader -D
使用
module.exports = {module: {
rules: [
{
test: /\.css$/,
use: ['style-loader','css-loader']
},
],
}
}
完整代码:
const path = require('path')console.log(path.join(__dirname,'/build'))
module.exports = {
mode: "production",
entry: './src/js/app.js', // 入口文件
output: {
"path": path.join(__dirname,'/build'), // 决定出口文件在哪里
"filename": "bundle.js"// 设置出口文件的名字。默认情况下,它叫main.js
},
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader','css-loader']
},
],
}
}
我们看下输出的 .js 包
bundle.js中有一些js代码,它在运行时,会自动在.html文件中追加style标签,并输出样式。
扩展
eval("var api = __webpack_require__(/*! ../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js */ \"./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js")
再去node_modules\style-loader\dist\runtime\injectStylesIntoStyleTag.js
找下insertStyleElement
这个方法,你就可以发现这个过程。
functioninsertStyleElement(options) {var style = document.createElement('style');
var attributes = options.attributes || {};
if (typeof attributes.nonce === 'undefined') {
var nonce = typeof __webpack_nonce__ !== 'undefined' ? __webpack_nonce__ : null;
if (nonce) {
attributes.nonce = nonce;
}
}
Object.keys(attributes).forEach(function (key) {
style.setAttribute(key, attributes[key]);
});
if (typeof options.insert === 'function') {
options.insert(style);
} else {
var target = getTarget(options.insert || 'head');
if (!target) {
thrownewError("Couldn't find a style target. This probably means that the value for the 'insert' parameter is invalid.");
}
target.appendChild(style);
}
return style;
}
此时浏览器就可以渲染样式了。
这里大家要注意 loader 的配置顺序。
小节 css-loader 帮助webpack 把.css 打包进去 style-loader 把打包的 .css 进行转换通过函数以 style标签的形式插入到 html 中。
扩展小知识** @import 用来引入另一个 css 文件。
语法
@import url;@import url list-of-media-queries;
@import [ <string> | <url> ] [ <media-query-list> ]?;
解释
- url:是一个表示要引入资源位置的
](https://developer.mozilla.org/zh-CN/docs/Web/CSS/string) 或者 [
。 这个 URL 可以是绝对路径或者相对路径。 要注意的是这个 URL 不需要指明一个文件; 可以只指明包名。 list-of-media-queries 是一个逗号分隔的 媒体查询 条件列表,决定通过URL引入的 CSS 规则 在什么条件下应用。如果浏览器不支持列表中的任何一条媒体查询条件,就不会引入URL指明的CSS文件。
实例
- css文件中用法
/* 方法一*/@import'test.css';
/* 方法二*/
@import url(test.css);
/* @import url list-of-media-queries;*/
@import"common.css" screen, projection;
@import url('landscape.css') screen and (orientation:landscape);
- js 文件中用法
import'test.css';
2. 使用 less-loader 处理 .less 文件
安装
npm i less-loader -D// 不用在安装 less
npm i less-loader less -D
less-loader: 加载 less 文件并且把 .less 语法的代码转换成 .css
配置
module.exports = {module: {
rules: [
{
test:/\.less$/,
use:['style-loader','css-loader','less-loader']
}
],
}
}
完整代码
const path = require('path')console.log(path.join(__dirname,'/build'))
module.exports = {
mode: "development", // development production
entry: './src/js/app.js', // 入口文件
output: {
"path": path.join(__dirname,'/build'), // 决定出口文件在哪里
"filename": "bundle.js"// 设置出口文件的名字。默认情况下,它叫main.js
},
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader','css-loader']
},
{
test:/\.less$/,
use:['style-loader','css-loader','less-loader']
}
],
}
}
这里大家要注意下 less 文件的 loader顺序
use:['style-loader','css-loader','less-loader']
原理:先执行 less-loader 加载 .less 并转换成 css 把转换的结果给 css-loader ,css-loader 把结果在处理给 style-loader , 如果只配置 less-loader webpback 无法识别 css 格式。因为每个 test 都是一个处理模块 webpack 不会把 test:/.css/ 的规则用来处理 /.less/
代码改造
index.less
@import "style.css";body{
div {
border:4px solid #ccc;
width: 50%;
height: 200px;
margin:30px auto;
box-shadow: 3px 3px 3px #ccc;
background-color: #fff;
text-align: center;
}
}
app.js
// node 模块化导入const {updateDom} = require('./tool');
// 引入 less 文件
import'../css/index.less'
// 引入 css 文件
// import './../css/style.css';
// es6 模块化导入
import {log} from'./tooles6';
updateDom('app','传智播客')
log('测试webpack是否能识别es6的模块化')
执行打包命令并且在浏览器中查看
3. 使用 url-loader file-loader 处理图片资源
前端开发不可避免的使用各种图片资源
代码改造
index.less 文件
@import "style.css";body{
div {
border:4px solid #ccc;
width: 50%;
height: 200px;
margin:30px auto;
box-shadow: 3px 3px 3px #ccc;
background-color: #fff;
text-align: center;
background-image: url(./../img/webpack-png.png);
}
}
安装 url-loader
npm i url-loader - D
配置
module.exports = {module: {
rules: [
{
test:/\.png/,
use:['url-loader']
}
],
}
}
执行
npm run build
结果
我们发现只有一个js文件,那是因为 url-loader 把图片文件转换成了 base 64。
优点:减少网络请求。
缺点: 增加了 js包大小。
base64 一般比图片会大一点点。
如何选择?
小文件可以转换成 base 64,大文件不推荐。
url-loader 高级配置
我们使用loader 的时候,之前是 use:['xxx-loader']
,如果想详细的设置loader可以如下
通用规则
use:[{
loader:'xxx-loader',
options:{
}}
]
如果你不是很了解可以通过 npm 去找对应的loader,例如
配置完成后的代码
const path = require('path')console.log(path.join(__dirname,'/build'))
module.exports = {
mode: "development", // development production
entry: './src/js/app.js', // 入口文件
output: {
"path": path.join(__dirname,'/build'), // 决定出口文件在哪里
"filename": "bundle.js"// 设置出口文件的名字。默认情况下,它叫main.js
},
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader','css-loader']
},
{
test:/\.less$/,
use:['style-loader','css-loader','less-loader']
},
{
test:/\.png/,
use:[{
loader:'url-loader',
options:{
limit:3*1024// 3* 1024b = 3kb
}
}]
}
],
}
}
执行 build结果如下:
这是因为我们通过配置 url-loder 使得它只处理 3k 一下的图片,并转换成 base64,如果需要处理大于 3kb的需要使用 file-loader 。
安装 file-loader
npm i file-loader -D
执行代码结果
这个时候我们发现并没有 配置 file-loader 就可以直接起作用了。
注意
浏览器查看
此时页面上面并不会显示图片,因为 file-loader 仅仅把图片复制过去。这时候我们查看路径,浏览器中是找不到路径的。这时候右键查看图片路径,我们可以很清楚的看到我们的图片路径位置是不对的
原因
上述代码设置了 limit 选项,意思是当图片体积小于 8192 字节时,会转换成 base 编码字符串,当图片体积大于 8192 字节时,默认会使用 file-loader。
解决方案 (如果大家看着笔记去学习,这里建议了解下直接跳过,因为后面通过 webpack 新增的 plugin 配置就会解决这个问题,不要浪费时间在这里)
修改 css 引用路径为file-loader处理图片后的路径。
工具 mini-css-extract-plugin 参考下面的内容配置
但是 mini-css-extract-plugin 通常是项目打包的时候才会用到。
扩展配置
我们的 url-loader 功能强大,它可以处理多种格式的文件,那么怎么优化配置 呢?具体如下
{test:/(\.png|\.jpg|\.svg)/,
use:[{
loader:'url-loader',
options:{
limit:3*1024 // 3* 1024b = 3kb
}
}]
}
其实就是使用正则表达式把我们想用 url-loader 处理的文件写在 test里面这样就可以匹配啦。
优化配置 通过配置 name 可以修改 打包之后图片的名称和输出位置
{test:/\.png/,
use:[{
loader:'url-loader',
options:{
limit:3*1024, // 3* 1024b = 3kb
name:'img/[name].[ext]'
}
}]
}
由于我们的 output 路径写的式 build 所以这里的name 可以成上面的样子,name 是原来文件名称 ext是文件类型
测试svg文件
代码改造
index.less
@import "style.css";body{
background: url(./../img/webpack-svg.svg);
div {
border:4px solid #ccc;
width: 50%;
height: 200px;
margin:30px auto;
box-shadow: 3px 3px 3px #ccc;
background-color: #fff;
text-align: center;
background-image: url(./../img/webpack-png.png);
}
}
执行打包
因为我们的svg图片小于 3k 所以 url-loader 把svg资源转成了 base64 大到了js里面
loader 小结
如何使用
- 根据文件类型下载对应的loader。
- 配置loader。
2. plugin 插件
介绍
1. 目的
插件在于解决 loader 无法实现的其他事。
2. 作用
plugin是用于扩展webpack的功能,
3. 常用 plugin 总结
html-webpack-plugin
功能:把我们自已写的.html文件复制到指定打包出口目录下,并引入相关的资源代码。
mini-css-extract-plugin
功能:这个插件帮助我们把css代码提取到一个独立的文件中(而不是以style的方式嵌在html文件中)。
clean-webpack-plugin
在生成打包文件之前,把目录清空掉。
实例
1. mini-css-extract-plugin
安装过程
- 下载插件
npm i mini-css-extract-plugin -D
- 在配置文件中引入
webpack.config.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
修改 webpack.config.js 的 module.exports 中的 rules
module.exports = {
module:{
rules:[
{
// 替换 style-loadr 为 {loader: MiniCssExtractPlugin.loader}这个配置是我们项目打包上线常用的写法。
test:/\.less$/,
use:[{loader: MiniCssExtractPlugin.loader},'css-loader','less-loader']
},
]
}
}
在 webpack.config.js 的 module.exports 增加 plugins。所有的插件都需要在这里面new 一下
plugins:[
new MiniCssExtractPlugin({
// [name], [hash] 是占位符
// name: 表示入口文件的名称
// hash: 一串随机值,是用于区别于本次打包与其它打包的过程。由于源文件有变化,则每次打包时hash都不同
filename: '[name]-[hash].css',
})
]
完整代码
const path = require('path')
+const MiniCssExtractPlugin = require('mini-css-extract-plugin');
console.log(path.join(__dirname,'/build'))
module.exports = {
mode: "development", // development production
entry: './src/js/app.js', // 入口文件
output: {
"path": path.join(__dirname,'/build'), // 决定出口文件在哪里
"filename": "bundle.js", // 设置出口文件的名字。默认情况下,它叫main.js
},
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader','css-loader']
},
{
test:/\.less$/,
+ use:[{loader: MiniCssExtractPlugin.loader},'css-loader','less-loader']
},
{
test:/(\.png|\.jpg|\.svg)/,
use:[{
loader:'url-loader',
options:{
limit:3*1024, // 3* 1024b = 3kb
}
}]
}
],
},
+ plugins:[
new MiniCssExtractPlugin({
// [name], [hash] 是占位符
// name: 表示入口文件的名称
// hash: 一串随机值,是用于区别于本次打包与其它打包的过程。由于源文件有变化,则每次打包时hash都不同
filename: '[name]-[hash].css',
})
]
}
执行打包命令
注意
这时后我们的 index.html 路径是不对的
我们的index.html 没有引用,这时候打开浏览器是看不到样式的,这时候我看额可以手动修改下 css 文件的引用地址。
2. html-webpack-plugin
- 安装
npm i html-webpack-plugin -D
- 在配置文件中引入。
webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');
- 在 webpack.config.js 的 plugins 中 new HtmlWebpackPlugin并配置
plugins: [new HtmlWebpackPlugin({ // 打包输出HTML
minify: { // 压缩HTML文件
removeComments: true, // 移除HTML中的注释
collapseWhitespace: true, // 删除空白符与换行符
minifyCSS: true// 压缩内联css
},
filename: 'index.html',
template: path.resolve('./index.html') // 指定模块的位置
})
]
删除 html 中的引用
<!DOCTYPE html><html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- <link rel="stylesheet" href="https://juejin.im/post/src/css/style.css"> -->
</head>
<body>
<div id="app"></div>
</body>
<!--
不通过webpack打包
<script src="https://juejin.im/post/5f14f886f265da2306247f7b/tool.js"></script>
<script src="https://juejin.im/post/index.js"></script>
-->
<!-- 使用webpack 打包生成的文件路径 -->
<!-- <script src="https://juejin.im/post/build/bundle.js"></script> -->
</html>
执行代码结果
build 里面多了一个 html。
删除HtmlWebpackPlugin 压缩的配置项
plugins: [new HtmlWebpackPlugin({ // 打包输出HTML
filename: 'index.html',
template: path.resolve('./index.html') // 指定模块的位置
})
]
打包后的结果
我们发现 url-loader 之前处理路径有问题的背景图片也显示出来了。
这些配置项我们同样可以在 npm 包的网站中找到,不需要去记住。接下来我们在添加一个插件去巩固下我们的知识。
3. clean-webpack-plugin
下载插件
npm i clean-webpack-plugin -D
配置文件webpack.config.js
const { CleanWebpackPlugin } = require('clean-webpack-plugin')module.exports = {
plugins: [
new CleanWebpackPlugin()
]
}
执行效果
全部代码
const path = require('path')const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
console.log(path.join(__dirname,'/build'))
module.exports = {
mode: "development", // development production
entry: './src/js/app.js', // 入口文件
output: {
"path": path.join(__dirname,'/build'), // 决定出口文件在哪里
"filename": "bundle.js", // 设置出口文件的名字。默认情况下,它叫main.js
},
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader','css-loader']
},
{
test:/\.less$/,
use:[{loader: MiniCssExtractPlugin.loader},'css-loader','less-loader']
},
{
test:/(\.png|\.jpg|\.svg)/,
use:[{
loader:'url-loader',
options:{
limit:3*1024, // 3* 1024b = 3kb
}
}]
}
],
},
plugins:[
new MiniCssExtractPlugin({
// [name], [hash] 是占位符
// name: 表示入口文件的名称
// hash: 一串随机值,是用于区别于本次打包与其它打包的过程。由于源文件有变化,则每次打包时hash都不同
filename: '[name]-[hash].css',
}),
new HtmlWebpackPlugin({ // 打包输出HTML
minify: { // 压缩HTML文件
removeComments: true, // 移除HTML中的注释
collapseWhitespace: true, // 删除空白符与换行符
minifyCSS: true// 压缩内联css
},
filename: 'index.html',
template: path.resolve('./index.html') // 指定模块的位置
}),
new CleanWebpackPlugin()
]
}
plugin 使用小结
plugin 用来增强 webpack 的能力
有了上面三个插件的使用经验我们总结下安装插件的步骤和注意点
- npm 包下载插件。
- 在配置文件中引入插件。
- 在 plugin的数组中 new 这个插件。
注意:
- 有些插件是直接导出的函数,而有些插件是导出的对象,例如
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
,当我们引用npm 包报错时候可以去 npm 包官网查看下使用 demo。 - 所有的插件都一定会在 plugins 数组里面通过 new 实例化。
- 插件在 plugins 中的顺序不是它调用的顺序,它的调用顺序和 webpack 执行过程有关系。
3. webpack-dev-server
目的: 在开发过程中实时更新我们的代码。
如何配置?
使用 npm 下载包
npm i webpack-dev-server -D
在配置文件最外层配置
module.exports = {
// 配置 webpack-dev-server的选项
devServer: {
host: '127.0.0.1', // 配置启动ip地址
port: 8081, // 配置端口
open: true // 配置是否自动打开浏览器
}
// 其它配置
}
修改 package.json 的快速启动配置
"scripts": {
"build": "webpack",
+ "dev":"webpack-dev-server"
},
执行新配置的命令
npm run dev
这时我们的浏览器就打开了,并且端口号是 8081,如果我们不想让我们的项目端口号和其他的项目冲突,可以去掉 port webpback 就会根据当前 系统端口占用情况自动生成一个端口号。
小结
webpack-dev-server 解决了我们开发过程中代码实时预览的问题,给我们的开发代来了方便,它的功能不仅仅如此,还可通过它配置跨越等功能。
3. webpoack 处理 .vue 文件
介绍
1 . 目的
通过webpack 可以处理打包 .vue 文件
配置
代码准备
vue 文件 /vuecomponents/App.vue
<template><div>
vue组件 {{title}}
</div>
</template>
<script>
exportdefault {
name: '',
data() {
return {
title:'webpack-vue-这里的vue单文件组件'
}
}
}
</script>
/js/main.js
import Vue from "vue"import App from '../vuecomponents/app.vue'
new Vue({
render(h) {
return h(App)
},
}).$mount("#app")
我们这里引用了 vue 所有要在 npm 中下载 vue
npm i vue -D
分析
- 我们新增 main.js 所以要修改配置文件 entry
- 我们要让webpack 识别 .vue 所以要安装 vue-loader
- 需要解析 .vue 的模板所以要有 vue-template-compiler
- 需要处理 .vue 内部的 style 所有要有 vue-style-loader
安装依赖
npm i vue-loader vue-template-compiler vue-style-loader -D
修改配置 webpack.config.js
修改 entry
entry: './src/js/main.js',
给.vue文件添加loader
添加VueLoaderPlugin
Vue-loader在15.*之后的版本都是 vue-loader的使用都是需要伴生 VueLoaderPlugin的。
vue-style-loader 和 之前的 file-loader类似不需要单独配置。
{// 如果是.vue文件,使用如下的loader
test: /\.vue$/,
loader: 'vue-loader'
}
const VueLoaderPlugin = require('vue-loader/lib/plugin')
上面这段代码是官网提供的配置实例
plugins:[new VueLoaderPlugin()
]
完整代码
const path = require('path')const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const VueLoaderPlugin = require('vue-loader/lib/plugin')
module.exports = {
mode: "development", // development production
entry: './src/js/main.js', // 入口文件
output: {
"path": path.join(__dirname,'/build'), // 决定出口文件在哪里
"filename": "bundle.js", // 设置出口文件的名字。默认情况下,它叫main.js
},
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader','css-loader']
},
{
test:/\.less$/,
use:[{loader: MiniCssExtractPlugin.loader},'css-loader','less-loader']
},
{
test:/(\.png|\.jpg|\.svg)/,
use:[{
loader:'url-loader',
options:{
limit:3*1024, // 3* 1024b = 3kb
name:'img/[name].[ext]'
}
}]
},
{
// 如果是.vue文件,使用如下的loader
test: /\.vue$/,
loader: 'vue-loader'
}
],
},
plugins:[
new MiniCssExtractPlugin({
// [name], [hash] 是占位符
// name: 表示入口文件的名称
// hash: 一串随机值,是用于区别于本次打包与其它打包的过程。由于源文件有变化,则每次打包时hash都不同
filename: '[name]-[hash].css',
}),
new HtmlWebpackPlugin({ // 打包输出HTML
filename: 'index.html',
template: path.resolve('./index.html') // 指定模块的位置
}),
new CleanWebpackPlugin(),
new VueLoaderPlugin()
],
devServer: {
host: '127.0.0.1', // 配置启动ip地址
port: 8081, // 配置端口
open: true// 配置是否自动打开浏览器
}
}
执行命令效果
小结
- 处理 .vue 我们已经分析了 就是需要loader。
- 由此可以得出 webpack 的模块化其实并不复杂,我们在使用它去为我们的项目打包的时候通过要处理的文件类型,目的去 npm 包网站上或者 webpack网站中找到对应的依赖包就可以
- 我们要掌握的是 webpack 的通常用法,和能够明白在打包过程中为什么会有错误,以及可以通过 webpack 提供的信息去配置。
总结
- webpack 是一个打包工具
- 在 webpack 的世界里一切皆模块。
- loader 帮助 webpack 去翻译不同的文件让 webpack 可以把它们打包
- plugin 插件完善了 webpack 打包功能
- vue-cli 也是基于 webpack 开发实现的
以上是 看完你就会用 webpack 了 的全部内容, 来源链接: utcz.com/a/34063.html