webpack原理 (3)

至此已经完成了modules的处理,接下来需要处理的就是怎么生成bundle.js,分析bundle时已经指出我们需要关注的地方只有modules的拼接,至于自执行函数中的内容都是基本都是固定的,不需要额外的处理

如何使用模版引擎打包模块的代码呢?

使用模版引擎ejs创建模版,模版的内容就是webpack打包生成的内容,只需要根据Compiler中modules进行遍历即可,还需要关注的是return __webpack_require__(__webpack_require__.s = "<%-entry%>"),这里传入的是配置文件的入口,也是自执行函数第一次执行时的参数

创建ejs的模板文件output.ejs,需要关注的只有两个地方,其它地方使用默认的代码

// 第一次执行的参数就是配置的entry return __webpack_require__(__webpack_require__.s = "<%-entry%>"); // 拼接函数需要的形参 modules { <% for (let k in modules) {%> "<%-k%>": (function (module, exports, __webpack_require__) { eval(`<%-modules[k]%>`); }), <%}%> }

为Compiler增加一个emitFile方法,用于根据模板生成打包的bundle文件,在start函数中的depAnalyse之后进行调用

/** * 根据写好的模板 创建文件 */ emitFile(){ // 已经创建好的 ejs 模版 const template = this.getSource(path.join(__dirname, '../template/output.ejs')) // 使用 ejs 进行编译 const result = ejs.render(template, { entry: this.entry, modules: this.modules }) // 获取输出路径和文件名 const { path: filePath, filename } = this.output const outputPath = path.join(filePath, filename) // 打包生成bundle 并放在指定的目录下 fs.writeFile(outputPath, result, (err) => { console.log(err ? err : '打包生成bundle完成'); }) }

到目前为止,已经可以进行简单的模块打包,可以将index.js、parent.js和child.js进行简单的打包,这里仅仅是支持最简单的webpack用法打包

loader

loader是webpack的重要核心功能之一,也是使用频率非常高的,主要功能就是将代码按照预期的结果进行加工处理,生成最终的代码后输出,因此掌握loade的基本机制是很有必要的。loader的使用也是非常简单的,其基本配置和用法这里不再赘述,接下来一起看看如何在自己的webpack-theory中添加解析loader和如何编写一个自己的loader。

自制loader

在为webpack-theory添加处理loader的能力之前,先看看如何在webpack中实现一个自己的loader

webpack中loader,主要步骤如下

读取webpack.config.js配置文件的module.rules配置项,进行倒序迭代(rules的每项匹配规则按倒序匹配)

根据正则匹配到对应的文件类型,同时再批量导入loader函数

默认是倒序迭代调用所有的loader函数(loader从右到左,从下到上),也可以自己来控制这个顺序

最后返回处理后的代码

当想要在webpack中增加处理cass文件能力的时候,会进行loader的配置

{ test:/\.scss$/, use:['style-loader', 'css-loader', 'sass-loader'] }

sass-loader其实就是一个函数,根据test的匹配规则,将以.scss结束的文件内容读取出来,然后将匹配到的文件内容作为参数传递给一个函数,这个函数将sass文件的内容按照规则进行加工处理成浏览器能够识别的css并输出,所以loader的本质就是一个函数,接受一个参数,这个参数就是匹配到的文件里面的代码。同理,css-loader和style-loader也是这样的处理流程,只是内部做的事情不同。

function handlerScss(sourceCode){ // 这里就是将scss文件的内容,按照规则进行加工、处理,结果就是浏览器能够识别解析的css,并将其返回 return newSourceCode }

接下来实现一个自己的简单loader,将之前的parent.js和child.js中的信息使用loader处理为msg

// 将js文件中的 信息 换成 msg module.exports = function (source) { return source.replace(/信息/g, 'msg') }

在webpack中配置loader

{ test:/\.js/, use:['./loader/handlerLoader1.js'] }

使用npx webpack打包之后,可以看到打包的代码中已经将原有代码中的信息更换为msg

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpdwzs.html