• webpack(四)plugin


    定义

    和loader的区别

    • loader:文件加载器,能够加载资源,并对这些文件进行一些处理,诸如编译、压缩等,最终一起打包到指定的文件中。
    • plugin:赋予了webpack各种灵活的功能,例如打包优化、资源管理、环境变量注入等,目的是解决loader无法实现的其它事。
      在这里插入图片描述
      loader运行在打包文件之前,plugin在整个编译周期都起作用
      webpack运行的生命周期中会广播出许多事件,plugin可以监听这些事件,在合适的时机通过webpack提供的api改变输出结果。
      对于loader,实际上是一个转换器,将A文件进行编译形成B文件,操作的是文件,比如将A.scssA.less转化为B.css,单纯的文件转换过程。

    特性

    本质是一个具有apply方法的js对象
    apply方法会被webpack compiler调用,并且在整个编译生命周期都可以访问compiler对象
    compiler hooktap方法的第一个参数,应是驼峰式命名的插件名称

    const pluginName = 'ConsoleLogOnBuildWebpackPlugin';
    
    class ConsoleLogOnBuildWebpackPlugin {
      apply(compiler) {
        compiler.hooks.run.tap(pluginName, (compilation) => {
          console.log('webpack 构建过程开始!');
        });
      }
    }
    
    module.exports = ConsoleLogOnBuildWebpackPlugin;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    生命周期:

    • entry-option :初始化 option
    • run
    • compile: 真正开始的编译,在创建 compilation 对象之前
    • compilation :生成好了 compilation 对象
    • make 从 entry 开始递归分析依赖,准备对每个模块进行 build
    • after-compile: 编译 build 过程结束
    • emit :在将内存中 assets 内容写到磁盘文件夹之前
    • after-emit :在将内存中 assets 内容写到磁盘文件夹之后
    • done: 完成所有的编译过程
    • failed: 编译失败的时候

    常见Plugin

    clean-webpack-plugin

    构建时,清除dist包

    npm install --save-dev clean-webpack-plugin
    
    const { CleanWebpackPlugin } = require('clean-webpack-plugin')
    module.exports = {
    plugins: [
            new CleanWebpackPlugin()
        ]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    测试,在dist中添加一个test.txt文件,重新运行打包命令,test.txt消失

    html-webpack-plugin

    构建时,帮助我们自动创建一个index.html文件,并把打包生成的js 模块引⼊到该 html

     npm i html-webpack-plugin -D
     
     const HtmlWebpackPlugin = require('html-webpack-plugin')
     module.exports = {
    plugins: [
            new HtmlWebpackPlugin({
             title: "My App", //修改页面的title
           filename: "app.html", // 
           template: "./public/index.html" //指定index文件位置,以我提供的html模板为基准生成index.html文件
            })
        ]
    }
    
    
    <!--./public/index.html-->
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title><%=htmlWebpackPlugin.options.title%></title>
    </head>
    <body>
        <h1>html-webpack-plugin</h1>
    </body>
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    测试,创建public/index.html文件,添加一些内容,打包后在dist中生成index.html文件会包含public/index.html文件中的内容

    DefinePlugin

    在这里插入图片描述
    给我们自定义模板中填充数据,定义常亮填充数据
    使用内置插件DefinePlugin

    new DefinePlugin({
                BASE_URL: '"./"'//希望是同级进行查找,相当于把值原封不动的拿出去 是./ 所以需要再包一层
            })
    
    • 1
    • 2
    • 3

    babel-loader

    babel原理

    为什么需要babel:开发时写了ts、jsx、es6+等,需要转换为浏览器可以识别的
    安装核心:npm i @babel/core (为了能在命令行使用npm i @babel/cli -D)

    命令行转化npx babel src --out-dir build,项目中多了build/js/index.js文件,但是没有对箭头函数和const关键字进行转换
    继续安装npm i @babel/plugin-transform-arrow-functions -D,命令行npx babel src --out-dir build --plugins=@babel/plugin-transform-arrow-functions,发现箭头函数完成了转换

    const title='前端'
    const foo = () =>{
        console.log(title)
    }
    foo()
    
    const title = '前端';
    const foo = function () {
      console.log(title);
    };
    foo();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    继续完成constvar的转化,npm i @babel/plugin-transform-block-scoping -D

    var title = '前端';
    var foo = function () {
      console.log(title);
    };
    foo();
    
    • 1
    • 2
    • 3
    • 4
    • 5

    babel会结合插件对js代码进行转换
    我们实际开发提供了一个预设npm i @babel/preset-env -D,防止我们所需要什么转换还需要自己去安装,这是一个集合包含了大部分的babel插件
    npx babel src --out-dir build --presets=@babel/preset-env
    添加了严格模式

    "use strict";
    
    var title = '前端';
    var foo = function foo() {
      console.log(title);
    };
    foo();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    babel-loader处理

    npm i babel-loader
    会根据我们.browserslistrc文件中的配置去进行兼容处理,如果我们同时配置了target,则会根据target为主进行打包

    module.exports = {
    ...
    module: {
            rules: [
            ...,
             {
                test: /.\.js$/,
                    use: [{
                        loader:'babel-loader',
                        options:{
                            [presets:['@babel/preset-env',{targets:'chrome 91'}]]
                        }
                    }]
                }
    ]
    }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    babel-loader相关的配置文件

    • babel.config.js(json) 目前是多包管理的方式,推荐使用这种方式
    • babelrc.json(js)babel7之前使用

    项目中新建babel.config.js文件

    module.exports = {
        presets: ['@babel/preset-env']
    }
    
    • 1
    • 2
    • 3
    // webpack.config.js
    {
                    test: /.\.js$/,
                    use: ['babel-loader']
                }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    polyfill

    webpack4中是自带的配置,在webpack5之后为了节省包大小,去掉了,需要手动配置npm i @babel/polyfill --save
    Babel 中默认只转换新的 JavaScript 句法,例如箭头函数、扩展运算符等。但是不会转换新的 API,像是Set、Maps、Iterator、Generator 、Symbol、Reflect 等全局对象,以及一些定义在全局对象上的方法都不会进行转译。如果想使用这些新的对象和方法,则需要为当前环境提供一个 polyfill 垫片。

    在这里插入图片描述
    拆分为两个,建议安装这两个npm i core-js regenerator-runtime

    //  babel.config.js
    module.exports = {
        presets: [
            ['@babel/preset-env', {
                // false 默认 不对当前的处理做polyfill的填充
                // usage preset-env不具备promise,使用这会对promise处理,依据用户代码中使用的新语法进行填充 需要corejs的版本为3
                // entry 根据当前的浏览器筛选去觉得如何处理
                useBuiltIns: 'usage', 
                corejs:3 
            }]
        ]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在这里插入图片描述
    问题:很有可能我们项目的包中也对Promise做了一个处理,此时会出现两个定义,所以需要做一下排除

    {
                    test: /.\.js$/,
                    exclude:/node_modules/,
                    use: ['babel-loader']
                }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    copy-webpack-plugin

    复制文件或目录到执行区域,如vue的打包过程中,如果我们将一些文件放到public的目录下,那么这个目录会被复制到dist文件夹中
    npm i copy-webpack-plugin -D

    new CopyWebpackPlugin({
        patterns:[
            {
                from:"public",
                globOptions:{
                    ignore:[
                        '**/index.html'
                    ]
                }
            }
        ]
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    复制的规则在patterns属性中设置:

    • from:设置从哪一个源中开始复制
    • to:复制到的位置,可以省略,会默认复制到打包的目录下
    • globOptions:设置一些额外的选项,其中可以编写需要忽略的文件
  • 相关阅读:
    LeetCode动态规划
    libcurl库
    未来展望:Starday供应链火力全开,为跨境电商再添动力!
    接口性能优化
    如何去云服务器申请环境跑深度学习模型
    Mysql数据库 12.SQL语言 触发器
    vue router
    弹性响应蒸馏 | 用弹性响应蒸馏克服增量目标检测中的灾难性遗忘
    数据结构与算法之一道题感受算法(算法入门)
    判断点是否在贝塞尔曲线(Bézier curve)上的方法
  • 原文地址:https://blog.csdn.net/cwjxyp/article/details/132690764