这部分内容接上一篇webpack
-js
模块的实现一文。在src
下新建文件index.css
,简单设置个样式,如下:
// index.css
body {
background: lightcoral;
}
现在文件结构如下:
然后在入口文件index.js
中引入该样式文件:
执行指令npx webpack --mode development
会报错,告诉我们没有安装相应的解析该文件的loader
:
下面我们尝试在已经实现的js
模块zlpack.js
中写一个loader
:
首先建立个概念loader
的本质就是个函数,所以我们新建一个函数styleLoader
,现在就可以判断script
中的文件名后缀是否是css
,如果是的话就要将该name
对应的content
用styleLoader
处理,在styleLoader
中将传入的content
解析成style
标签的形式,加入处理css
文件的zlpack.js
如下:
#! /usr/bin/env node
let entry = '../src/index.js';
let output = '../dist/main.js';
let fs = require('fs');
let path = require('path');
let ejs = require('ejs');
let script = fs.readFileSync(entry, 'utf8');
let modules = [];
// 负责将结果进行更改 更改后继续执行
let styleLoader = function(source) {
// source代表的就是样式文件中的内容
return `
let style = document.createElement('style');
style.innerHTML = ${JSON.stringify(source).replace(/\\r\\n/g, '')};
document.head.appendChild(style)
`
};
script = script.replace(/require\(['"](.+?)['"]\)/g, function() {
let name = path.join('../src', arguments[1]);
let content = fs.readFileSync(name, 'utf8');
// 如果name匹配到了.css后缀 content交给styleLoader处理
if(/\.css$/.test(name)) {
content = styleLoader(content);
};
modules.push({
name,
content
});
return `__webpack_require__('${name}')`;
});
let template = `
(function(modules) {
function __webpack_require__(moduleId) {
var module = {
exports: {}
};
modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
return module.exports;
}
return __webpack_require__("<%-entry%>");
})
({
"<%-entry%>": (function(module, exports, __webpack_require__) {
eval(\`<%-script%>\`);
})
<%for(let i=0; i<modules.length; i++) {
let module = modules[i];%>,
"<%-module.name%>": (function(module, exports, __webpack_require__) {
eval(\`<%-module.content%>\`);
})
<%}%>
});`
let result = ejs.render(template, {
entry,
script,
modules
});
fs.writeFileSync(output, result);
console.log('编译成功');
下面执行zlpack
命令,看打包生成的main.js
文件:
(function(modules) {
function __webpack_require__(moduleId) {
var module = {
exports: {}
};
modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
return module.exports;
}
return __webpack_require__("../src/index.js");
})
({
"../src/index.js": (function(module, exports, __webpack_require__) {
eval(`let result = __webpack_require__('..\src\a.js');
__webpack_require__('..\src\index.css')
console.log(result);`);
}),
"..\src\a.js": (function(module, exports, __webpack_require__) {
eval(`module.exports = "happy coding!"`);
}),
"..\src\index.css": (function(module, exports, __webpack_require__) {
eval(`let style = document.createElement('style');
style.innerHTML = "body {background: lightcoral}";
document.head.appendChild(style)`);})
});
可以看出,在zlpack
中,index.css
文件中的内容已经被解析到main.js
中了:
(function(modules) {
function __webpack_require__(moduleId) {
var module = {
exports: {}
};
modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
return module.exports;
}
return __webpack_require__("../src/index.js");
})
({
"../src/index.js": (function(module, exports, __webpack_require__) {
eval(`let result = __webpack_require__('..\src\a.js');
__webpack_require__('..\src\index.css')
console.log(result);`);
}),
"..\src\a.js": (function(module, exports, __webpack_require__) {
eval(`module.exports = "happy coding!"`);
}),
"..\src\index.css": (function(module, exports, __webpack_require__) {
eval(`let style = document.createElement('style');
style.innerHTML = "body {background: lightcoral}";
document.head.appendChild(style)`);})
});
在浏览器中运行:
可以看到背景色已经变成我们设置引入的css
文件中的颜色了。这样我们就实现了一个简单的styleloader
了。