-
loader:file-loader:处理静态资源模块
loader:file-loader
原理是把打包入口中识别出的资源模块,移动到输出目录,并且返回一个地址名称所以我们什么时候用file-loader呢?
场景:就是当我们需要模块,仅仅是从源代码挪移到打包目录,就可以使用files-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: blue;
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"]
}
样式⾃动添加前缀:
https://caniuse.com/
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就是⼀个函数,声明式函数,不能⽤箭头函数
拿到源代码,作进⼀步的修饰处理,再返回处理后的源码就可以了
官⽅⽂档:https://webpack.js.org/contribute/writing-a-loader/
接⼝⽂档:https://webpack.js.org/api/loaders/
简单案例
- 创建⼀个替换源码中字符串的loader
//index.js
console.log("hello world");
//replaceLoader.js
module.exports = function (source) {
console.log(source, this, this.query);
return source.replace('world', 'china')
};
//需要⽤声明式函数,因为要上到上下⽂的this,⽤到this的数据,该函数接受⼀个参数,是源码
- 在配置⽂件中使⽤loader
//需要使⽤node核⼼模块path来处理路径
const path = require('path')
module: {
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: "china"
}
}
]
}]
},
//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("world", options.name);
return source.replace("world", 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);
};
// this.callback(
// err: Error | null,
// content: string | Buffer,
// sourceMap ?: SourceMap,
// meta ?: any
// );
- this.async:如果loader⾥⾯有异步的事情要怎么处理呢
const loaderUtils = require("loader-utils");
module.exports = function (source) {
const options = loaderUtils.getOptions(this);
setTimeout(() => {
const result = source.replace("world", options.name);
return result;
}, 1000);
};
//先⽤setTimeout处理下试试,发现会报错
我们使⽤this.asycn来处理,他会返回this.callback
const loaderUtils = require("loader-utils");
module.exports = function (source) {
const options = loaderUtils.getOptions(this);
//定义⼀个异步处理,告诉webpack,这个loader⾥有异步事件,在⾥⾯调⽤下这个异步
//callback 就是 this.callback 注意参数的使⽤
const callback = this.async();
setTimeout(() => {
const result = source.replace("kkb", options.name);
callback(null, result);
}, 3000);
};
- 多个loader的使⽤
//replaceLoader.js
module.exports = function (source) {
return source.replace("开课吧", "word");
};
//replaceLoaderAsync.js
const loaderUtils = require("loader-utils");
module.exports = function (source) {
const options = loaderUtils.getOptions(this);
//定义⼀个异步处理,告诉webpack,这个loader⾥有异步事件,在⾥⾯调⽤下这个异步
const callback = this.async();
setTimeout(() => {
const result = source.replace("world", options.name);
callback(null, result);
}, 3000);
};
//webpack.config.js
module: {
rules: [
{
test: /\.js$/,
use: [
path.resolve(__dirname, "./loader/replaceLoader.js"),
{
loader: path.resolve(__dirname, "./loader/replaceLoaderAsync.js"),
options: { name: "china" }
}] // use: [path.resolve(__dirname, "./loader/replaceLoader.js")]
}]
},
顺序,⾃下⽽上,⾃右到左
- 处理loader的路径问题
resolveLoader: {
modules: ["node_modules", "./loader"]
},
module: {
rules: [
{
test: /\.js$/,
use: [
"replaceLoader",
{
loader: "replaceLoaderAsync",
options: {
name: "china"
}
}]
// use: [path.resolve(__dirname, "./loader/replaceLoader.js")]
}]
},
参考:loader API
https://webpack.js.org/api/loaders
mini-css-extract-plugin
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, "css-loader"]
}
new MiniCssExtractPlugin({ filename: "[name][chunkhash:8].css" })
chunk:⼀个⼊⼝肯定是⼀个chunk,但是⼀个chunk不⼀定只有⼀个依赖
hash :
Chunkhash
Contenthash
- 未完待续 。。。。