loader
运行在打包文件之前,plugin
在整个编译周期都起作用webpack
运行的生命周期中会广播出许多事件,plugin
可以监听这些事件,在合适的时机通过webpack
提供的api
改变输出结果。loader
,实际上是一个转换器,将A文件进行编译形成B文件,操作的是文件,比如将A.scss
或A.less
转化为B.css
,单纯的文件转换过程。本质是一个具有apply
方法的js
对象
apply
方法会被webpack compiler
调用,并且在整个编译生命周期都可以访问compiler
对象
compiler hook
的 tap
方法的第一个参数,应是驼峰式命名的插件名称
const pluginName = 'ConsoleLogOnBuildWebpackPlugin';
class ConsoleLogOnBuildWebpackPlugin {
apply(compiler) {
compiler.hooks.run.tap(pluginName, (compilation) => {
console.log('webpack 构建过程开始!');
});
}
}
module.exports = ConsoleLogOnBuildWebpackPlugin;
生命周期:
构建时,清除dist包
npm install --save-dev clean-webpack-plugin
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
module.exports = {
plugins: [
new CleanWebpackPlugin()
]
}
测试,在dist
中添加一个test.txt
文件,重新运行打包命令,test.txt
消失
构建时,帮助我们自动创建一个index.html
文件,并把打包生成的js
模块引⼊到该 html
中
npm i html-webpack-plugin -D
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
plugins: [
new HtmlWebpackPlugin({
title: "My App", //修改页面的title
filename: "app.html", //
template: "./public/index.html" //指定index文件位置,以我提供的html模板为基准生成index.html文件
})
]
}
<!--./public/index.html-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title><%=htmlWebpackPlugin.options.title%></title>
</head>
<body>
<h1>html-webpack-plugin</h1>
</body>
</html>
测试,创建public/index.html
文件,添加一些内容,打包后在dist
中生成index.html
文件会包含public/index.html
文件中的内容
给我们自定义模板中填充数据,定义常亮填充数据
使用内置插件DefinePlugin
new DefinePlugin({
BASE_URL: '"./"'//希望是同级进行查找,相当于把值原封不动的拿出去 是./ 所以需要再包一层
})
为什么需要babel
:开发时写了ts、jsx、es6+
等,需要转换为浏览器可以识别的
安装核心:npm i @babel/core
(为了能在命令行使用npm i @babel/cli -D
)
命令行转化npx babel src --out-dir build
,项目中多了build/js/index.js
文件,但是没有对箭头函数和const关键字进行转换
继续安装npm i @babel/plugin-transform-arrow-functions -D
,命令行npx babel src --out-dir build --plugins=@babel/plugin-transform-arrow-functions
,发现箭头函数完成了转换
const title='前端'
const foo = () =>{
console.log(title)
}
foo()
const title = '前端';
const foo = function () {
console.log(title);
};
foo();
继续完成const
到var
的转化,npm i @babel/plugin-transform-block-scoping -D
var title = '前端';
var foo = function () {
console.log(title);
};
foo();
babel
会结合插件对js
代码进行转换
我们实际开发提供了一个预设npm i @babel/preset-env -D
,防止我们所需要什么转换还需要自己去安装,这是一个集合包含了大部分的babel
插件
npx babel src --out-dir build --presets=@babel/preset-env
添加了严格模式
"use strict";
var title = '前端';
var foo = function foo() {
console.log(title);
};
foo();
npm i babel-loader
会根据我们.browserslistrc
文件中的配置去进行兼容处理,如果我们同时配置了target
,则会根据target
为主进行打包
module.exports = {
...
module: {
rules: [
...,
{
test: /.\.js$/,
use: [{
loader:'babel-loader',
options:{
[presets:['@babel/preset-env',{targets:'chrome 91'}]]
}
}]
}
]
}
}
babel-loader相关的配置文件
babel.config.js(json)
目前是多包管理的方式,推荐使用这种方式babelrc.json(js)
在babel7
之前使用项目中新建babel.config.js
文件
module.exports = {
presets: ['@babel/preset-env']
}
// webpack.config.js
{
test: /.\.js$/,
use: ['babel-loader']
}
在webpack4
中是自带的配置,在webpack5
之后为了节省包大小,去掉了,需要手动配置npm i @babel/polyfill --save
Babel 中默认只转换新的 JavaScript
句法,例如箭头函数、扩展运算符等。但是不会转换新的 API
,像是Set、Maps、Iterator、Generator 、Symbol、Reflect
等全局对象,以及一些定义在全局对象上的方法都不会进行转译。如果想使用这些新的对象和方法,则需要为当前环境提供一个 polyfill
垫片。
拆分为两个,建议安装这两个npm i core-js regenerator-runtime
// babel.config.js
module.exports = {
presets: [
['@babel/preset-env', {
// false 默认 不对当前的处理做polyfill的填充
// usage preset-env不具备promise,使用这会对promise处理,依据用户代码中使用的新语法进行填充 需要corejs的版本为3
// entry 根据当前的浏览器筛选去觉得如何处理
useBuiltIns: 'usage',
corejs:3
}]
]
}
问题:很有可能我们项目的包中也对Promise
做了一个处理,此时会出现两个定义,所以需要做一下排除
{
test: /.\.js$/,
exclude:/node_modules/,
use: ['babel-loader']
}
复制文件或目录到执行区域,如vue
的打包过程中,如果我们将一些文件放到public
的目录下,那么这个目录会被复制到dist
文件夹中
npm i copy-webpack-plugin -D
new CopyWebpackPlugin({
patterns:[
{
from:"public",
globOptions:{
ignore:[
'**/index.html'
]
}
}
]
})
复制的规则在patterns属性中设置: