知识回顾
这里的loader是webpack的核心概念之一,它的作用是将webpack无法识别的其他类型的文件(如css文件,图片)转换为有效 模块,webpack只能理解JavaScript和JSON文件。
在配置loader时有2个重要属性:
- test 正则表达式,用于匹配哪些文件
- use 指定哪些loader对匹配到的文件进行处理
一般情况下,我们像这样使用已有的loader
module: {
rules: [
{
test: /\.css$/
use: ['style-loader', 'css-loader']
}
]
}
那么,如何使用我们自定义的loader呢?以下面的例子为例:
一个简单的loader
-
创建空目录awesome-webpack
-
在awesome-webpack运行npm init -y
-
运行npm i webpack webpack-cli -D
-
创建项目目录如下
image.png
main.css,内容如下:
body {
margin: 0 auto;
padding: 0 20px;
max-width: 800px;
background: #f4f8fb;
}
index.js, 内容如下:
import './main.css'
此时如果没有在webpack.config.js配置处理css文件的loader直接打包就会报错,
self-loader.js是自定义的loader,我们使用这个自定义的loader来处理css文件,在webpack.config.js里配置如下:
const path = require('path')
const config = {
entry: path.join(__dirname, 'src/index.js'),
mode: 'none',
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: './src/self-loader',
options: {
name: '参数'
}
}
]
}
]
}
}
module.exports = config
重点来了,这个loader究竟长什么样呢?
自定义loader向外暴露一个方法,而这个方法接收一个参数,这个参数的值即为匹配到的文件的内容字符串,结果返回一个字符串。
self-loader.js
module.exports = function (source) {
console.log(source)
console.log(this.query)
return `let style = document.createElement('style');style.innerHTML = ${JSON.stringify(source)}; document.head.append(style)`
}
上面打印内容如下:
image.png
可见,接收参数source是文件内容,而this.query是配置文件里的options的值,这里使用到this就不要用箭头函数。
自定义loader最后还要返回结果,由于一个文件可以被多个loader处理,那么最后一个处理的loader一定要返回一段能被webpack识别的字符串,如JS代码。
注意loader是运行在Node.js环境里的,所以应该符合CommonJS规范,所以自定义loader是使用module.exports 而不是export default对外暴露方法。
打包出来的结果:
/******/ (() => { // webpackBootstrap
/******/ var __webpack_modules__ = ([
/* 0 */,
/* 1 */
/***/ (() => {
let style = document.createElement('style');style.innerHTML = "body {\r\n margin: 0 auto;\r\n padding: 0 20px;\r\n max-width: 800px;\r\n background: #f4f8fb;\r\n}\r\n\r\n\r\n/* console.log('css') */"; document.head.append(style)
/***/ })
/******/ ]);
/************************************************************************/
/******/ // The module cache
/******/ var __webpack_module_cache__ = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ var cachedModule = __webpack_module_cache__[moduleId];
/******/ if (cachedModule !== undefined) {
/******/ return cachedModule.exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = __webpack_module_cache__[moduleId] = {
/******/ // no module.id needed
/******/ // no module.loaded needed
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/************************************************************************/
/******/ /* webpack/runtime/compat get default export */
/******/ (() => {
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = (module) => {
/******/ var getter = module && module.__esModule ?
/******/ () => (module['default']) :
/******/ () => (module);
/******/ __webpack_require__.d(getter, { a: getter });
/******/ return getter;
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/define property getters */
/******/ (() => {
/******/ // define getter functions for harmony exports
/******/ __webpack_require__.d = (exports, definition) => {
/******/ for(var key in definition) {
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ }
/******/ }
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/hasOwnProperty shorthand */
/******/ (() => {
/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ })();
/******/
/******/ /* webpack/runtime/make namespace object */
/******/ (() => {
/******/ // define __esModule on exports
/******/ __webpack_require__.r = (exports) => {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/ })();
/******/
/************************************************************************/
var __webpack_exports__ = {};
// This entry need to be wrapped in an IIFE because it need to be in strict mode.
(() => {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony import */ var _main_css__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
/* harmony import */ var _main_css__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_main_css__WEBPACK_IMPORTED_MODULE_0__);
// import createTag from "./createTag"
// import icon from './icon.jpg'
// let ele = createTag('h1', '一级标题')
// let img = createTag('img')
// // img.src = icon
// document.body.append(ele, img)
})();
/******/ })()
;
到这里,一个最简单的自定义loader就完成了。
扩展
loader-utils
这个工具用来分析参数,需要使用npm安装
网友评论