写在前面
我们知道webpack其实不仅是javascript模块打包工具,更是整个前端项目即前端工程的模块打包工具,可以通过webpack去管理前端项目中任意类型的资源文件。
如何加载资源模块
首先,我们在项目的src目录下添加一个样式文件main.css。目录结构如下:
- |--03-loader
- |--src
- |--main.css
- |--package.json
- |--webpack.config.js
- /* main.css */
- body{
- margin:0 auto;
- padding:0 20px;
- max-width:800px;
- background:yellow;
- }
接下来,在webpack.config.js配置中的入口文件路径进行更改为main.css文件路径,执行webpack直接进行打包css资源文件。
- const path = require("path")
- module.exports = {
- // 样式文件路径
- entry:"src/main.css",
- output:{
- filename:"bundle.js",
- path:path.join(__dirname,"output")
- },
- mode:"none"
- }
如果我们不进行其他的任何配置,此时直接执行打包命令,会报错提示我们报错,因为只能是使用js文件作为打包入口。之所以会这样,那是因为在webpack中默认解析的是js语法,而对于非js语法需要先进行Loader,再在配置文件中另外进行配置loader。
css文件通过css-loader进行处理,再提交给webpack进行打包生成js文件。
- $ npm i css-loader -D
但是,当你此时执行打包命令后,尝试在你页面中使用生成bundle.js文件,会发现刚刚的main.css模块并没有起作用,那么我们需要额外添加一个style-lodaer加载器,这样就能正常工作了。样式没有生效的原因是:css-loader只会把css模块加载到js代码中,而不会直接使用此模块。
那么,在你安装完style-lodaer后,将配置文件中的use属性修改为数组,将style-lodaer也配置进去。因为loader数组的加载顺序是自下而上的,所以style-lodaer应该配置在css-loader上面。
- //main.js
- import "./style.css"
- console.log("hello yichuan");
- /* style.css */
- body{
- margin:0 auto;
- padding:0 20px;
- max-width:800px;
- background:yellow;
- }
loader加载器是整个webpack打包配置的核心,因为需要通过它去实现任意类型文件的打包,这样最后都进行打包生成了js文件。
那么,为什么webpack要在js中载入css文件,而不是将样式文件和行为进行分离?
这是因为,真正需要其他资源的并不是整个项目中,而是某个模块需要使用。
假设在进行页面开发某个局部功能时,需要使用到一个样式模块和一个图片文件,如果你还是将这些资源单独引入到html文件中,然后再到js中添加对应的逻辑代码,试想如果后期不需要这个局部功能,那么就需要同时删除JS中的代码和html中的资源文件引入,也就是需要同时维护多条线。然而,此时你遵循webapck的导入设计,所有资源加载都是通过js代码控制,那么后期只需要维护js代码就行。
为什么要建立这种JS文件导入其他资源的依赖关系,这是因为:
逻辑上比较合理:因为JS确实需要这些资源文件配合才能实现整体功能
配合webapck这类工具的打包:能够确保在上线时,资源不会缺失,而且都是必要的。
接下来,我们进行简易的loader开发,目标是实现对md文件的打包。
- // index.js
- import mrakdown from "hello.md"
- <!-- hello.md -->
- ## 你好呀
- //md-loader.js
- const md = require("./hello.md")
- module.exports = source => {
- // 加载到的模块内容
- console.log("加载到的模块内容==>",source);
- // 返回值就是最终打包的结果
- return "你好呀"
- }
- //webpack.config.js
- const path = require("path")
- module.exports = {
- // 样式文件路径
- entry:"./src/index.js",
- output:{
- filename:"bundle.js"
- },
- mode:"none",
- module:{
- rules:[{
- test:/\.md$/,//根据打包过程中所遇文件路径记性匹配是否使用此loader
- use:"./md-loader"//指定具体使用的loader
- }]
- }
- }
此时执行打包命令后报错,提示我们加载对应的loader。这是因为打包的每个loader形成一个链条,每个loader都依赖于另一个loader的引入,最终打包出来的必须是js文件。对此,我们有处理方法:
- 将我们自定义的md-laoder加载器的输出设置为js语法
- 安装对应的loader加载器
- module.exports = source => {
- // 加载到的模块内容
- console.log("加载到的模块内容==>",source);
- // 返回值就是最终打包的结果
- return "console.log('你好呀')";
- }
那么当我们使用合适的Loader加载器将md文件解析为html模块,需要先进行安装marked,安装完后在md-loader.js导入模块,然后进行解析。
- $ npm i marked
- //./md-loader.js
- const marked = require("marked")
- module.exports = source => {
- // 1.将md文件转为html字符串
- const html = marked(source);
- return `export default ${JSON.stringify(html)}`
- }
参考文章
《webpack原理与实践》
《webpack中文文档》
写在最后
loader机制是webpack核心内容,因为有了loader机制webpack才能足以支撑整个前端项目模块化,实现通过webpack去加载任何想要的资源。