webpack(7) 样式处理和图片处理之手写loader
一. webpack模块中的require发生的事情:
webpack模块中的require("xx");与nodejs里的require是不一样的. webpack会在读取后进行loader转换, 再进行抽象语法数分析,
比如require("src/assets/index.css") ; webpack中的require会被分析成为依赖函数, 读取参数的文件;
在webpack读取文件之后, 经过loader后形成转换后的代码, 然后交给内部的AST分析, 然后在形成模块依赖列表;
二. 手写cssloader
根据以上这个流程, 可以自己手写cssloader:
(1) index.js引入css文件;
(2)在读取完css文件后,本loader将文件的内容作为一个<style></style>的innerHTML, 然后放到head标签中;
(3)经过loader处理的css文件会作为 js模块, 将js代码存放到chunk中, 最终和index.js合并打包输出
(4) html引用的时候会执行输出的index.js, 就执行了这段代码后在页面上渲染.
//index.js import "./src/assets/index.css"; //注意, 这里即使用require, 也和nodejs的require不一样,和commonjs的引入一样,是webpack作为依赖关系确定的标识
1 //mycssloader.js 2 module.exports = function(source){ 3 var str = ` 4 var style = document.createElement("style"); 5 style.innerHTML = \`${source}\`; 6 document.head.appendChild(style); 7 ` 8 return str; 9 }
webpack.config.js
三.手写
图片: 页面上的静态img标签, 和 js动态生成的图片document.createElement("img").;img.src = 引入的内容
动态图片: ajax从服务器上获取.
1 import src from "./assets/imgs/down.jpg" 2 //通过引入图片文件作为src的属性值 3 var img = document.createElement("img"); 4 img.src = src; 5 document.body.appendChild(img);
module.exports = { module: { rules: [ { test: /\.css$/, use: ["./src/myloader/mycssloader"] }, { test: /\.(png|jpg|gif|webp|jpeg)$/i, use: [{ loader: "./src/myloader/myimgloader", //自己手写的loader解析图片 options: { limit: 900, } }] },
分两种情况, 如果图片大小 大于limit , 就生成文件,返回引入地址,否则, 直接转成base64格式返回;
1 const fs = require("fs"); 2 const loderUtils = require("loader-utils"); 3 4 function imgLoader(buffer) { 5 // 这个source是二进制, 用buffer表示 6 7 var src; 8 if (loderUtils.getOptions(this) && loderUtils.getOptions(this).limit > buffer.byteLength) { //图片文件尺寸小于limit 9 src = getBase64(buffer); 10 } else { 11 src = getFilePath.call(this, buffer); 12 13 } 14 15 return `module.exports=\`${src}\``;//注意, 这一步让我对loader有了更深入的了解, 这个return的内容, 是需要执行的,webpack的函数函数内本身没有执行的; 16 17 } 18 imgLoader.raw = true; //处理的是原始数据, source是一个buffer 19 20 function getFilePath(buffer) {//生成一个新的图片, 添加到最终资源中, 并返回路径 21 var filename = loderUtils.interpolateName(this, "[contenthash:5].[ext]", { 22 content: buffer 23 }) 24 this.emitFile(filename, buffer) 25 return filename; 26 } 27 28 function getBase64(buffer) { //将图片转换成base64编码 29 return 'data:image/png;base64,' + buffer.toString("base64") 30 } 31 32 module.exports = imgLoader;