style-loader
一、认识
style-loader
核心逻辑是在 loader.patch
阶段执行, loader
函数本身是一个空函数。在 pitch
中, 核心处理逻辑如下:
-
获得对应样式文件: 通过
import style from "!!remainingRequest"
获取对应样式,remainingRequest
表示use: ['style-loader']
位于style-loader
之后的loader
路径,!!remainingRequest
表示仅本次引入的inline-loader
生效, 避免造成死循环。webpack
遇到import style from "!!remainingRequest"
会递归编译import
语句中的路径模块, 编译结果为:import style from "!!remainingRequest"
// 编译为:
/* harmony import */ var _Users_zhangwenqiang_bolawen_blog_docusaurus_webpack_test_webpack_bolawen01_node_modules_pnpm_css_loader_6_8_1_webpack_5_89_0_node_modules_css_loader_dist_cjs_js_Users_zhangwenqiang_bolawen_blog_docusaurus_webpack_test_webpack_bolawen01_loaders_style_loader_example_index_css__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! !!./node_modules/.pnpm/css-loader@6.8.1_webpack@5.89.0/node_modules/css-loader/dist/cjs.js!./loaders/style-loader/example/index.css */ "./node_modules/.pnpm/css-loader@6.8.1_webpack@5.89.0/node_modules/css-loader/dist/cjs.js!./loaders/style-loader/example/index.css"); -
在页面创建
style
节点, 将样式内容赋给style
节点然后将节点加入head
标签即可
设计理念:
-
将
style-loader
处理逻辑放入loader
中,css-loader
返回的是一段js
脚本, 我们需要处理脚本中的import/require
逻辑并执行这一段脚本, 获得样式内容 -
将
style-loader
处理逻辑放入pitch
中, 通过import style from "!!remainingRequest"
语句, 并返回非undefined
发生熔断。这样, 在style-loader.pitch
之后webpack
不会在去执行use
中配置的后续loader
, 对import style from "!!remainingRequest"
编译执行, 然后获得样式内容。
也就是是说: 通过pitch loader
中import someThing from !!${remainingRequest}
剩余loader
,从而实现上一个loader
的返回值是js
脚本,将脚本交给webpack
去编译执行。
二、实现
function styleLoader(sourceCode) {}
styleLoader.pitch = function (remainingRequest, previousRequest, data) {
const script = `
import style from "!!${remainingRequest}";
const styleEl = document.createElement('style');
styleEl.innerHTML = style;
document.head.appendChild(styleEl);
`;
return script;
};
module.exports = styleLoader;
三、测试
3.1 test/webpack/bolawen01/loaders/style-loader/example/webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: path.resolve(__dirname, './index.js'),
devtool: false,
mode: 'development',
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js'
},
module: {
rules: [
{
test: /\.css$/,
use: [path.resolve(__dirname, '../core/index.js'), 'css-loader']
}
]
},
plugins: [new HtmlWebpackPlugin()]
};
3.2 test/webpack/bolawen01/loaders/style-loader/example/index.js
require("./index.css");
3.3 test/webpack/bolawen01/loaders/style-loader/example/index.css
div{
color: red;
}
3.4 test/webpack/bolawen01/package.json
"style-loader": "webpack --config ./loaders/style-loader/example/webpack.config.js"