webpack自身的定位是一个模块打包器,他的的理念是万物皆模块。然而其自身只能处理 javascript
模块以及 json
模块,那么何以敢称万物皆可打包呢,这就引出了 loader
机制,loader
可将各式各样的引用资源进行转化,然后输出为 webpack 可以识别的 javascript 模块并进行打包处理。
基本配置
const path = require('path');
/**
* 为配置文件提供类型支持
* @type {import('webpack').Configuration}
*/
module.exports = {
entry: './src/index.js',
mode: 'development',
devtool: false,
output: {
path: path.join(__dirname, 'build'),
filename: 'main.js'
},
module: {
rules: [
{
test: /\.md$/,
loader: path.join(__dirname, './src/loaders/markdown-loader.js')
}
]
}
};
打包入口文件
// index.js
import markdown from './mark.md';
console.log(markdown);
// mark.md
### markdown loader
`markdown` 转为 JavaScript 模块代码
markdown-loader
依赖 marked 包,用于解析Markdown文件,并输出 html 代码
第一种处理方式
const { marked } = require('marked');
module.exports = (source) => {
let target = marked.parse(source);
// 输出的为 JavaScript 字符串,供后续 webpack 的处理
return `export default ${JSON.stringify(target)}`;
};
打包结果
/******/ var __webpack_modules__ = ({
/***/ "./src/mark.md":
/*!*********************!*\
!*** ./src/mark.md ***!
\*********************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ("<h3 id=\"markdown-loader\">markdown loader</h3>\n<p><code>markdown</code> 转为 JavaScript 模块代码</p>\n");
/***/ })
/******/ });
第二种处理方式,引入html-loader来处理html代码
// markdown-loader.js
const { marked } = require('marked');
module.exports = (source) => {
let target = marked.parse(source);
// return `export default ${JSON.stringify(target)}`;
/** 直接返回html,由 html-loader进行后续处理 */
return target
};
// webpack配置文件
const path = require('path');
/**
* @type {import('webpack').Configuration}
*/
module.exports = {
entry: './src/index.js',
mode: 'development',
devtool: false,
output: {
path: path.join(__dirname, 'build'),
filename: 'main.js'
},
module: {
rules: [
{
test: /\.md$/,
use: [
'html-loader', // 新增,处理由上一个loader返回的 html
path.join(__dirname, './src/loaders/markdown-loader.js')
]
}
]
}
};
打包结果
/******/ var __webpack_modules__ = ({
/***/ "./src/mark.md":
/*!*********************!*\
!*** ./src/mark.md ***!
\*********************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
// Module
var code = "<h3 id=\"markdown-loader\">markdown loader</h3>\n<p><code>markdown</code> 转为 JavaScript 模块代码</p>\n";
// Exports
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (code);
/***/ })
/******/ });
webpack整体打包结果分析
/******/ (() => { // webpackBootstrap
/******/ "use strict";
/******/ var __webpack_modules__ = ({
/***/ "./src/mark.md":
/*!*********************!*\
!*** ./src/mark.md ***!
\*********************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
// Module
var code = "<h3 id=\"markdown-loader\">markdown loader</h3>\n<p><code>markdown</code> 转为 JavaScript 模块代码</p>\n";
// Exports
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (code);
/***/ })
/******/ });
/************************************************************************/
/******/ // 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/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 isolated against other modules in the chunk.
(() => {
/*!**********************!*\
!*** ./src/index.js ***!
\**********************/
__webpack_require__.r(__webpack_exports__);
/* harmony import */ var _mark_md__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./mark.md */ "./src/mark.md");
console.log(_mark_md__WEBPACK_IMPORTED_MODULE_0__["default"]);
})();
/******/ })()
;
执行入口
var __webpack_exports__ = {};
// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk.
(() => {
/*!**********************!*\
!*** ./src/index.js ***!
\**********************/
__webpack_require__.r(__webpack_exports__);
/* harmony import */ var _mark_md__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./mark.md */ "./src/mark.md");
console.log(_mark_md__WEBPACK_IMPORTED_MODULE_0__["default"]);
})();
webpack_require.r
/******/ /* webpack/runtime/make namespace object exports下挂载 __esModule 属性,用于标记是否是ES模块代码 */
/******/ (() => {
/******/ // 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 });
/******/ };
/******/ })();
webpack_require 加载资源
/******/ // The module cache
/******/ var __webpack_module_cache__ = {};
/******/ function __webpack_require__(moduleId) { // moduleId 即为 "./src/mark.md"
/******/ // 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] 也就是__webpack_modules__["./src/mark.md"]
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/
/******/ // Return the exports of the module 返回 module.exports 对象
/******/ return module.exports;
/******/ }
webpack_modules["./src/mark.md"]
/******/ var __webpack_modules__ = ({
/***/ "./src/mark.md":
/*!*********************!*\
!*** ./src/mark.md ***!
\*********************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
// 标记 ES 模块
__webpack_require__.r(__webpack_exports__);
// 为 __webpack_exports__ 挂载 "default" 属性,并设置 "getter" 方法为 () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
// Module
var code = "<h3 id=\"markdown-loader\">markdown loader</h3>\n<p><code>markdown</code> 转为 JavaScript 模块代码</p>\n";
// Exports
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (code);
/***/ })
/******/ });
webpack_require.d
/******/ /* 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] }); // get: () => (__WEBPACK_DEFAULT_EXPORT__),当访问 exports.default 时,其值为 __WEBPACK_DEFAULT_EXPORT__也即是上文对应的 code 值
/******/ }
/******/ }
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/hasOwnProperty shorthand 对象的属性检测 */
/******/ (() => {
/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ })();
运行的结果
var _mark_md__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./mark.md */ "./src/mark.md")
// _mark_md__WEBPACK_IMPORTED_MODULE_0__["default"] => 创建的新module即__webpack_module_cache__[moduleId],并导出 exports 对象 => {exports: {default: () => "<h3 id=\"markdown-loader\">markdown loader</h3>\n<p><code>markdown</code> 转为 JavaScript 模块代码</p>\n"}} =>
// 通过 __webpack_require__.d 方法为 exports下的default属性设置了 getter 方法,所以_mark_md__WEBPACK_IMPORTED_MODULE_0__["default"] = "<h3 id=\"markdown-loader\">markdown loader</h3>\n<p><code>markdown</code> 转为 JavaScript 模块代码</p>\n"