简介
Webpack 是⼀个现代 JavaScript 应⽤程序的静态模块打包器(module bundler),当 webpack 处理应⽤程序时,它会递归地构建⼀个依赖关系图(dependency graph),其中包含应⽤程序需要的每个模块,然后将所有这些模块打包成⼀个或多个 bundle。
(Webpack是⼀个打包模块化JavaScript的⼯具,它会从⼊⼝模块出发,识别出源码中的模块化导⼊语句,递归地找出⼊⼝⽂件的所有依赖,将⼊⼝和其所有的依赖打包到⼀个单独的⽂件中)
是⼯程化、⾃动化思想在前端开发中的体现。
安装
-
环境准备 nodejs 版本参考官网发布的最新版本,可以提升webpack的打包速度
-
安装方式 局部安装(推荐)
npm init -y # 初始化npm配置⽂件
npm install --save-dev webpack # 安装核⼼库
npm install --save-dev webpack-cli # 安装命令⾏⼯具
# 安装最新的4.x稳定版本
npm i -D webpack@4.44.0
# 安装指定版本 npm i -D webpack@<version>
npm i webpack@4.43.0 webpack-cli@3.3.12 -D
// 检查版本
npx webpack -V
全部安装(不推荐)
# 安装webpack V4+版本时,需要额外安装webpack-cli
npm install webpack webpack-cli -g
# 检查版本 webpack -v
# 卸载
npm uninstall webpack webpack-cli -g
全局安装webpack,这会将你项⽬中的webpack锁定到指定版本,造成不同的项⽬中因为webpack依赖不同版本⽽导致冲突,构建失败
启动webpack
webpack默认配置
- webpack默认⽀持JS模块和JSON模块
- ⽀持CommonJS Es moudule AMD等模块类型
- webpack4⽀持零配置使⽤,但是很弱,稍微复杂些的场景都需要额外扩展
准备执行构建
- 新建src文件夹
- 新建 src/index.js、src/index.json、src/other.js
### index.js
const json = require("./index.json");//commonJS
import { add } from "./other.js";//es module
console.log(json, add(2, 3));
### index.json
{ "name": "JOSN" }
### other.js
export function add(n1, n2) {
return n1 + n2;
}
执行构建
# npx⽅式
npx webpack
# npm script
npm run test
修改package.json文件:
"scripts": {
"test": "webpack"
},
原理就是通过shell脚本在node_modules/.bin⽬录下创建⼀个软链接。
构建成功
我们会发现⽬录下多出⼀个 dist ⽬录,⾥⾯有个 main.js ,这个⽂件是⼀个可执⾏的JavaScript⽂件, ⾥⾯包含webpackBootstrap启动函数。
默认配置
const path = require('path');
moudle.exports = {
// 必填 webpack执行构建入口
entry: './src/index.js',
output: {
// 将所有依赖的模块合并并输出到main.js
filename: 'main.js',
// 输出文件存放路径,必须是绝对路径
path: path.resolve(__dirname,'./dist')
}
};
webpack配置核心概念
- chunk: 指代码块,一个chunk可能由多个模块组合而成,也用于代码合并与分割。
- bundle: 资源经过 Webpack 流程解析编译后最终输出的成果文件。
- entry: 顾名思义,就是入口起点。⽤来告诉 webpack ⽤哪个⽂件作为构建依赖图的起点。 webpack会根据entry递归的去寻找依赖,每个依赖都将被它处理,最后输出到打包成果中。
- output: output配置描述了webpack打包的输出配置,包含输出文件的命名、位置等信息。
- loader: 默认情况下,webpack仅⽀持 .js .json ⽂件,通过loader,可以让它解析其他类型的⽂件,充当翻译官的⻆⾊。理论上只要有相应的loader,就可以处理任何类型的⽂件。
- plugin: loader主要的职责是让webpack认识更多的文件类型,而plugin的职责则是让其可以控制构建流程,从而执行一些特殊的任务。插件的功能⾮常强⼤,可以完成各种各样的任务。
- mode:4.0开始,webpack⽀持零配置,旨在为开发⼈员减少上⼿难度,同时加⼊了mode的概念,⽤于指定打包的⽬标环境,以便在打包的过程中启⽤webpack针对不同的环境下内置的优化。
loader: file-loader:处理静态资源模块
loader: file-loader
原理是把打包⼊⼝中识别出的资源模块,移动到输出⽬录,并且返回⼀个地址名称
场景:就是当我们需要模块,仅仅是从源代码挪移到打包⽬录,就可以使⽤file-loader来处理, txt,svg,csv,excel,图⽚资源啦等等
npm install file-loader -D
案例:
module: {
rules: [
{
test: /\.(png|jpe?g|gif)$/,
//use使⽤⼀个loader可以⽤对象,字符串,两个loader需要⽤数组
use: {
loader: "file-loader",
// options额外的配置,⽐如资源名称
options: {
// placeholder 占位符 [name]⽼资源模块的名称
// [ext]⽼资源模块的后缀
// https://webpack.js.org/loaders/file-loader#placeholders
name: "[name]_[hash].[ext]",
//打包后的存放位置
outputPath: "images/"
}
}
}
]
},
import pic from './logo.png';
var img = new Image();
img.src = pic;
img.classList.add("logo");
var root = document.getElementById("root");
root.append(img);
css
@font-face {
font-family: "webfont";
font-display: swap;
src: url("webfont.woff2") format("woff2");
}
body {
background: blus;
font-family: "webfont" !important;
}
// webpack.config.js
{
test: /\.(eot|ttf|woff|woff2|svg)$/,
use: "file-loader"
}
url-loader file-loader加强版本
url-loader内部使⽤了file-loader,所以可以处理file-loader所有的事情,但是遇到jpg格式的模块, 会把该图⽚转换成base64格式字符串,并打包到js⾥。对⼩体积的图⽚⽐较合适,⼤图⽚不合 适。
npm install url-loader -D
案例
module: {
rules: [
{
test: /\.(png|jpe?g|gif)$/,
use: {
loader: "url-loader",
options: {
name: "[name]_[hash].[ext]",
outputPath: "images/",
//⼩于2048,才转换成base64
limit: 2048
}
}
}
]
}
样式处理:
- Css-loader 分析css模块之间的关系,并合成⼀个css
- Style-loader 会把css-loader⽣成的内容,以style挂载到⻚⾯的heade部分
npm install style-loader css-loader -D
{
test: /\.css$/,
use: ["style-loader", "css-loader"]
}
{
test:/\.css$/,
use: [
{
loader:"style-loader",
options: {
injectType: "singletonStyleTag" // 将所有的style标签合并成⼀个
}
},
"css-loader"
]
}
Less 样式处理
less-load 把less语法转换成css
$ npm install less less-loader --save-dev
案例:
loader有顺序,从右到左,从下到上
{
test: /\.scss$/,
use: ["style-loader", "css-loader", "less-loader"]
}
Postcss-loader
npm i postcss-loader autoprefixer -D
新建postcss.config.js
// webpack.config.js
{
test: /\.css$/,
use: ["style-loader", "css-loader", "postcss-loader"]
},
// postcss.config.js
module.exports = {
plugins: [
require("autoprefixer")({
overrideBrowserslist: ["last 2 versions", ">1%"]
})
]
};
- loader 处理webpack不⽀持的格式⽂件,模块
- ⼀个loader只处理⼀件事情
- loader有执⾏顺序
如何⾃⼰编写⼀个Loader
⾃⼰编写⼀个Loader的过程是⽐较简单的, Loader就是⼀个函数,声明式函数,不能⽤箭头函数 拿到源代码,作进⼀步的修饰处理,再返回处理后的源码就可以了
案例
- 创建⼀个替换源码中字符串的loader
// index.js
console.log("hello kkb");
// replaceLoader.js
module.exports = function(source){
console.log(source, this, this.query);
return source.replace('kkb','开课吧')
}
// 需要⽤声明式函数,因为要上到上下⽂的this,⽤到this的数据,该函数接受⼀个参数,是源码
- 在配置⽂件中使⽤loade
// 需要使⽤node核⼼模块path来处理路径
const path = require('path')
moodule: {
rules: [
{
test: /\.js$/,
use: path.resolve(__dirname, "./loader/replaceLoader.js")
}
]
}
- 如何给loader配置参数,loader如何接受参数?
- this.query
- loader-utils
// webpack.config.js
module: {
rules: [
{
test: /\.js$/,
use: [
{
loader: path.resolve(__dirname, "./loader/replaceLoader.js"),
options: {
name: "开课吧"
}
}
]
}
]
},
// replaceLoader.js
// const loaderUtils = require("loader-utils");//官⽅推荐处理loader,query的⼯具
module.exports = function(source){
// this.query 通过this.query来接受配置⽂件传递进来的参数
// return source.replace("kkb", this.query.name);
const options = loaderUtils.getOptions(this);
const result = source.replace("kkb", options.name);
return source.replace("kkb", options.name);
}
this.callback :如何返回多个信息,不⽌是处理好的源码呢,可以使⽤this.callback来处理
// replaceLoader.js
const loaderUtils = require("loader-utils");//官⽅推荐处理loader,query的⼯具
module.exports = function(source){
const options = loaderUtils.getOptions(this);
const result = source.replace("kkb", options.name);
this.callback(null, result);
};