美文网首页
webpack的loader和plugin

webpack的loader和plugin

作者: 风雅欢乐 | 来源:发表于2020-05-03 20:52 被阅读0次

    loader

    webpack loader: loader本质上是一个函数,它的作用是将某个源码字符串转换成另一个源码字符串返回。

    loader函数将在模块解析的过程中被调用,以得到最终的源码。按照loader配置的书写顺序, 多个loader从后往前依次调用, 后面一个loader的输出结果传入前一个loader继续处理.

    2020-01-13-09-35-44.png

    代码示例

    var loaderUtils = require('loader-utils');
    
    module.exports = function (sourceCode) {
        var options = loaderUtils.getOptions(this);
        var reg = new RegExp(options.changeVar, "g");
        return sourceCode.replace(reg, "var");
    }
    

    在配置文件中的options处书写的额外参数, 可以在loader函数内的this中读取到, webpack在this对象内放了很多东西. 使用load-utils包可以帮助我们解析this对象的内容.

    plugin

    loader的功能定位是转换代码,而一些其他的操作难以使用loader完成,比如:

    • 当webpack生成文件时,顺便多生成一个说明描述文件
    • 当webpack编译启动时,控制台输出一句话表示webpack启动了
    • 当xxxx时,xxxx
      这种类似的功能需要把功能嵌入到webpack的编译流程中,而这种事情的实现是依托于plugin的. webpack在编译的过程中有许多事件, 我们通过监听这些事件能够参与到编译过程的各个阶段, 并且有机会在这些阶段来实现我们的功能.

    plugin的本质是一个带有apply方法的对象, 习惯上我们会将该对象写成构造函数的模式.

    apply方法有一个参数compiler, compiler对象是在初始化阶段创建的, 整个webpack打包过程中只有一个compiler对象, 后续完成打包工作的是compiler对象内部创建的compilation(每一次具体的打包过程都会有新的compilation对象). apply方法会在创建好compiler对象后调用, 并向方法传入compiler.

    代码示例

    module.exports = class MyPlugin {
        
        constructor(filename = 'filelist.txt') {
            this.filename = filename;
        }
        
        apply(compiler) {
            // 在这里注册事件, 类似于window.onload
            compiler.hooks.emit.tap("MyPlugin-emit", function(compilation) {
                // 事件处理函数
                var fileList = [];
                for (const key in compilation.assets) {
                    var content = `[${key}] 大小: ${compilation.assets[key].size()}b`;
                    fileList.push(content);
                }
                var str = fileList.join("\n\n");
                compilation.assets[this.filename] = {
                    source() {
                        return str;
                    },
                    size() {
                        return str.length;
                    }
                };
            });
        }
    }
    

    常用扩展

    • css-loader: 将css代码转换为js代码, 将css中的其他依赖作为require导入, 以便webpack分析依赖
    • style-loader: 将css-loader转换后的代码进一步处理, 将样式加到页面的style元素中
    • MiniCssExtractPlugin: 将css文件单独抽离到输出目录(跟js打包方式一样, 一个chunk合并成一个css)
      • 它包含有一个plugin和一个loader
      • 在loader配置处以MiniCssExtractPlugin.loader的方式, 替换到原先的style-loader
    • clean-webpack-plugin: 清除输出目录
    • html-webpack-plugin: 自动生成页面
    • copy-webpack-plugin: 复制静态资源(html中直接引用静态资源, 希望把静态资源复制到输出目录)
    • webpack-dev-server: 开发服务器(既不是plugin, 也不是loader), 运行webpack-dev-server后, 做了以下操作
      1. 内部执行webpack命令, 传递命令参数
      2. 开启watch
      3. 注册hooks, 向webpack中注册钩子函数, 主要功能有: 将资源列表保存, 禁止webpack输出文件
      4. 用express开启一个服务器, 监听某端口
    • file-loader: 将导入的文件, 导出为一个有效url地址, 并将文件输出到输出目录
    • url-loader: 将依赖的文件转换为: 导出一个base64格式的字符串, 不生成文件到输出目录
      1. url-loader可以配置如果文件超过了设定的大小, 则不生成base64编码, 而是交给file-loader处理
      2. url-loader内部使用了file-loader, 它的配置项有些自身不用, 是传递给file-loader用的

    webpack内置插件

    所有的webpack内置插件都作为webpack的静态属性存在

    const webpack = require("webpack");
    new webpack.插件名(options);
    
    • DefinePlugin: 定义一些全局的常量
    • BannerPlugin: 为每个chunk生成的文件头部添加注释, 一般用于添加作者, 公司, 版权信息等
    • ProvidePlugin: 自动加载模块, 而不必导出import或require

    解决路径问题

    在某些情况下, 例如将图片用file-loader输出到dist/img目录下, js文件输出到dist/scripts目录下, 页面文件输出到dist/html目录下, 此时js对图片的引用会产生问题.

    这种问题发生的根本原因是: 模块中的路径来自于某个loader或plugin, 当产生路径时, loader或plugin只有相对于dist目录的路径, 并不知道该路径将在哪个资源中使用, 从而无法确定最终的正确路径.

    面对这种情况, 需要依靠webpack的配置publicPath解决.

    注意: publicPath通常在output配置项中, 本身没有任何作用, 但是某些loader和plugin会读取这个publicPath, 并且它们导出的地址前面, 拼接上这个配置. 通常output里配置为publicPath: "/" 这样, 文件的地址就变成了绝对路径.

    一般, 会用到publicPath的loader和plugin, 本身也会支持在自己的配置项中再单独配置publicPath项.

    相关文章

      网友评论

          本文标题:webpack的loader和plugin

          本文链接:https://www.haomeiwen.com/subject/kuyjghtx.html