美文网首页
Webpack使用入门

Webpack使用入门

作者: SpaceCat | 来源:发表于2022-12-26 12:40 被阅读0次

    这里介绍webpack的基本使用。

    1、打包js后引用

    1.1 文件准备

    在一个单独的目录中新建配置文件00_webpackhello/package.json

    {  
      "name": "00_webpackhello",  
      "version": "1.0.0",  
      "description": "",  
      "main": "index.js",  
      "scripts": {  
        "test": "echo \"Error: no test specified\" && exit 1",  
        "build": "webpack --mode development"  
      },  
      "keywords": [],  
      "author": "",  
      "license": "ISC",  
      "devDependencies":{  
        "webpack": "^5.74.0",  
        "webpack-cli": "^4.10.0"  
      }  
    }
    

    在同目录下新建配置文件00_webpackhello/webpack.config.js

    const path = require('path');  
      
    module.exports = {  
        entry: './src/main.js',  
        output: {  
            path: path.resolve(__dirname, 'dist'),  
            filename: 'bundle.js',  
        },  
    };
    

    在相同目录下新建src目录,并创建待打包的js文件。
    00_webpackhello/src/compute.js

    var testNum1 = 6, testNum2 = 3;  
    function add(a, b) {  
        return a + b;  
    }  
    function minus(a, b) {  
        return a - b;  
    }  
    function multiply(a, b) {  
        return a * b;  
    }  
    function divide(a, b) {  
        return a / b;  
    }  
    //这里导出一个默认变量  
    export {  
        add,  
        minus,  
        multiply,  
        divide  
    }
    

    00_webpackhello/src/main.js

    import * as tmp from './compute.js'  
    var num1 = 10, num2 = 2;  
    alert("testNum1: " + ", testNum2: " +  " " + tmp.add(num1, num2) + " " + tmp.minus(num1, num2)+ " " + tmp.multiply(num1, num2)+ " " + tmp.divide(num1, num2));
    

    添加gitignore配置文件00_webpackhello/.gitignore

    dist/  
    node_modules/
    

    新建一个测试html文件,用于引用打包后的js文件,看是否有效。
    00_webpackhello/index.html

    <!-- 其他省略 -->  
    <body>  
    <script src="dist/bundle.js"></script>  
    </body>
    

    1.2 环境安装

    在当前目录下执行如下npm install命令,npm会自动根据package.json配置文件中的依赖进行安装。

    $ npm install
    
    up to date in 692ms
    $ 
    

    执行完成后,这个目录下会生成一个package-lock.json配置文件,我们一般不用管它。同时,前面在package.json中配置的依赖,应该会自动安装到00_webpackhello/node_modules目录下。

    1.3 打包

    在当前目录下执行打包命令:

    $ npm run build
    
    > 00_webpackhello@1.0.0 build
    > webpack --mode development
    
    asset bundle.js 4.79 KiB [emitted] (name: main)
    runtime modules 670 bytes 3 modules
    cacheable modules 513 bytes
      ./src/main.js 219 bytes [built] [code generated]
      ./src/compute.js 294 bytes [built] [code generated]
    webpack 5.75.0 compiled successfully in 132 ms
    $ 
    

    在当前目录会新生成一个dist目录,其中包含打包生成的文件00_webpackhello/dist/bundle.js。打包之后的完整目录结构如下图。

    image.png

    1.4 测试

    这时候,如果在浏览器中打开前面创建的index.html,可以看到js已经生效。如下图。


    image.png

    2、打包为js依赖库

    2.1 直接作为依赖库引用报错

    前面的例子中,如果在index.html中直接写一个script标签,调用add函数,如下:

    <!-- 其他省略 -->  
    <body>  
    <script src="dist/bundle.js"></script>  
    <script>  
        alert(add(1,2));  
    </script>  
    </body>
    

    会报错add没有定义。这是因为在javascript的模块化语法里面,在每一个模块文件中定义的函数和变量都是局部变量,所以,在模块范围之外没法引用。

    2.2 依赖库打包配置说明

    webpack支持将js文件打包为依赖库,供其他人调用。通过library的配置可以支持指定库的名称, libraryTarget指定库打包出来的规范。
    其中,可选的值有“var、assign、this、window、global、commonjs、commonjs2、commonjs”。
    不同取值的打包行为说明如下:

    // var config  
    {  
        output: {  
            library: 'myLib',  
                filename: 'var.js',  
                libraryTarget: 'var'  
        }  
    }  
    // output  
    var myLib = (function (modules) { })({  
        './src/index.js': function (module, exports) { }  
    });  
    // ===============================================  
      
    // assign config  
    {  
        output: {  
            library: 'myLib',  
                filename: 'assign.js',  
                libraryTarget: 'assign'  
        }  
    }  
    // output: 少了个 var  
    myLib = (function (modules) { })({  
        './src/index.js': function (module, exports) { }  
    });  
    // ===============================================  
      
    // this config{  
    {  
        output: {  
            library: 'myLib',  
                filename: 'this.js',  
                libraryTarget: 'this'  
        }  
    }  
    // output  
    this["myLib"] = (function (modules) { })({  
        './src/index.js': function (module, exports) { }  
    });  
    // ===============================================  
      
    // window config  
    {  
        output: {  
            library: 'myLib',  
                filename: 'window.js',  
                libraryTarget: 'window'  
        }  
    }  
    // output  
    window["myLib"] = (function (modules) { })({  
        './src/index.js': function (module, exports) { }  
    });  
    // ===============================================  
      
    // global config  
    {  
        output: {  
            library: 'myLib',  
                filename: 'global.js',  
                libraryTarget: 'global'  
        }  
    }  
      
    // output:注意 target=node 的时候才是 global,默认 target=web下global 为 window  
    window["myLib"] = (function (modules) { })({  
        './src/index.js': function (module, exports) { }  
    });  
    // ===============================================  
      
    // commonjs config  
    {  
        output: {  
            library: 'myLib',  
                filename: 'commonjs.js',  
                libraryTarget: 'commonjs'  
        }  
    }  
    // output  
    exports["myLib"] = (function (modules) { })({  
        './src/index.js': function (module, exports) { }  
    });  
    // ===============================================  
      
    // amd config  
    {  
        output: {  
            library: 'myLib',  
                filename: 'amd.js',  
                libraryTarget: 'amd'  
        }  
    }  
    // output  
    define('myLib', [], function () {  
        return (function (modules) { })({  
            './src/index.js': function (module, exports) { }  
        });  
    });  
    // ===============================================  
      
    // umd config  
    {  
        output: {  
            library: 'myLib',  
                filename: 'umd.js',  
                libraryTarget: 'umd'  
        }  
    }  
    // output  
    (function webpackUniversalModuleDefinition(root, factory) {  
        if (typeof exports === 'object' && typeof module === 'object')  
            module.exports = factory();  
        else if (typeof define === 'function' && define.amd) define([], factory);  
        else if (typeof exports === 'object') exports['myLib'] = factory();  
        else root['myLib'] = factory();  
    })(window, function () {  
        return (function (modules) { })({  
            './src/index.js': function (module, exports) { }  
        });  
    });  
    // ===============================================  
      
    // commonjs2 config  
    {  
        output: {  
            library: 'myLib',  
                filename: 'commonjs2.js',  
                libraryTarget: 'commonjs2'  
        }  
    }  
    //output  
    module.exports = (function(modules) {})({  
        './src/index.js': function(module, exports) { }  
    });  
    // ===============================================  
      
    // umd2 config  
    {  
        output: {  
            library: 'myLib',  
                filename: 'umd2.js',  
                libraryTarget: 'umd2'  
        }  
    }  
    // output  
    (function webpackUniversalModuleDefinition(root, factory) {  
        if (typeof exports === 'object' && typeof module === 'object')  
            module.exports = factory();  
        else if (typeof define === 'function' && define.amd) define([], factory);  
        else if (typeof exports === 'object') exports['myLib'] = factory();  
        else root['myLib'] = factory();  
    })(window, function () {  
        return (function (modules) { })({  
            './src/index.js': function (module, exports) {  
            }  
        });  
    });  
    // ===============================================  
      
    // commonjs-module config  
    {  
        output: {  
            library: 'myLib',  
                filename: 'commonjs-module.js',  
                libraryTarget: 'commonjs-module'  
        }  
    }  
    // output  
    module.exports = (function (modules) { })({  
        './src/index.js': function (module, exports) { }  
    });  
    // ===============================================  
      
    // jsonp config  
    {  
        output: {  
            library: 'myLib',  
                filename: 'jsonp.js',  
                libraryTarget: 'jsonp'  
        }  
    }  
    // output  
    myLib((function (modules) { })({  
        './src/index.js': function (module, exports) { }  
    }));  
    // ===============================================
    

    简单说明见下图:


    image.png

    2.3 依赖库打包示例

    这里将前面的例子中的代码,打包为可以在script标签中引用的依赖库。
    首先,修改打包的配置文件00_webpackhello/webpack.config.js

    const path = require('path');
    
    module.exports = {
        entry: './src/main.js',
        output: {
            path: path.resolve(__dirname, 'dist'),
            filename: 'bundle.js',
            //指定打包后的库通过全局变量的方式暴露
            libraryTarget: "var",
            //指定打包后的库名
            library: "MATH"
        },
    };
    

    然后,修改测试文件00_webpackhello/index.html,在script标签中调用前面的依赖函数,如下。

    <!-- 其他省略 -->  
    <body>  
    <script src="dist/bundle.js"></script>  
    <script>  
        alert(MATH.add(1,2));  
    </script>  
    </body>
    

    这样,在00_webpackhello目录下执行npm run build打包命令之后,在浏览器中打开测试文件00_webpackhello/index.html,可以看到能够正常被调用。第一个alert弹出之后,第二个alert,也可以正常弹出,如下图:

    image.png

    实际上,这样打包之后,也可以在单独的js文件中引用。这里新建一个00_webpackhello/callTest.js文件:

    alert(MATH.multiply(22,2));
    

    在测试文件00_webpackhello/index.html中,引用这个文件,如下:

    <!-- 其他省略 -->  
    <body>  
    <script src="dist/bundle.js"></script>  
    <script src="callTest.js"></script>  
    <script>  
        alert(MATH.add(1,2));  
    </script>  
    </body>
    

    在浏览器中打开上述测试文件之后,可以看到三个alert框,说明在单独的js文件中,也可以被调用到。

    3、打包css

    3.1 将css打包到js中

    3.1.1 预处理器css-loader和style-loader简介

    这里需要用到两个预处理器css-loader和style-loader。css-loader的作用是解析css文件,包括解析@import等css自身语法,它会将解析后的css文件以字符串的形式打包到js文件中(但此时,css样式并不会生效,因为需要把css文件插入到html中才会生效)。style-loader的作用就是把js中的样式代码插入到html中。它的原理很简单,就是通过动态生成style标签并将其插入到html文件的head标签中。

    3.1.2 打包css到js示例

    在一个新的目录01_webpackhello中新建如下文件。
    npm配置文件,01_webpackhello/package.json

    {  
      "name": "00_webpackhello",  
      "version": "1.0.0",  
      "description": "",  
      "main": "index.js",  
      "scripts": {  
        "test": "echo \"Error: no test specified\" && exit 1",  
        "build": "webpack --mode development"  
      },  
      "keywords": [],  
      "author": "",  
      "license": "ISC",  
      "devDependencies": {  
        "css-loader": "^6.7.2",  
        "style-loader": "^3.3.1"  
      }  
    }
    

    webpack配置文件,01_webpackhello/webpack.config.js

    const path = require('path');  
      
    module.exports = {  
        entry: './src/main.js',  
        output: {  
            path: path.resolve(__dirname, 'dist'),  
            filename: 'bundle.js'  
        },  
        module: {  
            rules: [  
                {  
                    test: /\.css$/i,  
                    //执行顺序从右向左,将css-loader处理后的结果传给style-loader  
                    use: ['style-loader', 'css-loader'],  
                },  
            ],  
        },  
    };
    

    添加gitignore配置文件01_webpackhello/.gitignore

    dist/  
    node_modules/
    

    新建javascript代码,01_webpackhello/src/main.js

    import './css/all.css'; // 使用 ESM 方式引入  
    const name = 'Paopao';  
    alert('Hello ' + name);  
    console.log('Hello ' + name);
    

    新建css代码,01_webpackhello/src/css/all.css

    .text-primary {
        color: rgb(37, 37, 177);
    }
    

    新建一个测试打包效果的html文件,01_webpackhello/index.html

    <html>
    <head>
        <!-- 引入打包生成的 JavaScript -->
        <script src="dist/bundle.js"></script>
    </head>
    <body>
    <h1 class="text-primary" id="hello_h1">Hello World</h1>
    </body>
    </html>
    

    在该目录下执行npm install命令,npm会自动根据package.json配置文件中的依赖进行安装。
    然后,执行npm run build命令,就可以执行打包操作。打包后的目录结构如下。

    image.png

    这时候,在浏览器中打开前面新建的01_webpackhello/index.html,可以看到css已经生效,弹出alert框之后,字体显示为蓝色,如下。

    image.png

    3.2 处理css引入的图片

    3.2.1 file-loader简介

    file-loader是一个文件资源预处理器,作用是:处理文件导入语句(比如js的import ... from ...和css中的url())并替换成它的访问地址,同时把文件输出到相应的位置。

    3.2.2 处理css引入图片的打包示例

    首先,修改npm配置文件01_webpackhello/package.json

    {
      "name": "00_webpackhello",
      "version": "1.0.0",
      "description": "",
      "main": "index.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1",
        "build": "webpack --mode development"
      },
      "keywords": [],
      "author": "",
      "license": "ISC",
      "devDependencies": {
        "css-loader": "^5.0.2",
        "style-loader": "^2.0.0",
        "file-loader": "^5.1.0"
      }
    }
    

    注意:如果style-loader、css-loader、file-loader这几个的版本号不配套,会导致一个图片打包后生成两个,其中一个还不能用的情况。
    修改webpack配置文件,增加file-loader的处理,01_webpackhello/webpack.config.js

    const path = require('path');
    
    module.exports = {
       entry: './src/main.js',
       output: {
           path: path.resolve(__dirname, 'dist'),
           filename: 'bundle.js'
       },
       module: {
           rules: [
               {
                   test: /\.css$/I,
                   //执行顺序从右向左,将css-loader处理后的结果传给style-loader
                   use: ['style-loader', 'css-loader'],
               },
               {
                   test: /\.png$/,
                   use: "file-loader"
               }
           ],
       },
    };
    

    修改样式表文件,01_webpackhello/src/css/all.css

    .text-primary {  
        color: rgb(37, 37, 177);  
    }  
    body{  
        background: url("img/cat.png") no-repeat;  
    }
    

    同时,新增一个图片文件img/cat.png
    在该目录下执行npm install命令,npm会自动根据package.json配置文件中的依赖进行安装。
    然后,执行npm run build命令,就可以执行打包操作。打包后的目录结构如下。

    image.png

    这时,在浏览器中打开前面新建的01_webpackhello/index.html,可以看到css已经生效,弹出alert框之后,字体显示为蓝色,并且有背景图片,如下。

    image.png

    3.2.3 指定css引入图片打包后的文件名和存放路径

    前面的例子中,可以看出,css引用的图片在打包之后,文件名成了一个hash串。如果我们想要指定图片文件名和存放位置,只需要修改webpack配置文件,给file-loader传入options。如下。
    01_webpackhello/webpack.config.js

    const path = require('path');
    
    module.exports = {
        entry: './src/main.js',
        output: {
            path: path.resolve(__dirname, 'dist'),
            filename: 'bundle.js'
        },
        module: {
            rules: [
                {
                    test: /\.css$/I,
                    //执行顺序从右向左,将css-loader处理后的结果传给style-loader
                    use: ['style-loader', 'css-loader'],
                },
                {
                    test: /\.png$/,
                    use: {
                        loader: "file-loader",
                        options: {
                            name: 'img/[name].[ext]'
                        }
                    }
                }
            ],
        },
    };
    

    执行npm run build命令,就可以执行打包操作。打包后的目录结构如下。

    image.png

    ,在浏览器中打开前面新建的01_webpackhello/index.html,可以看到css已经生效,弹出alert框之后,字体显示为蓝色,并且有背景图片,如下。

    image.png

    3.3 将css打包成到单独的文件

    还是前面的例子,代码不变,修改打包的相关配置。
    首先,修改npm配置文件01_webpackhello/package.json,增加mini-css-extract-plugin依赖:

    {  
      "name": "00_webpackhello",  
      "version": "1.0.0",  
      "description": "",  
      "main": "index.js",  
      "scripts": {  
        "test": "echo \"Error: no test specified\" && exit 1",  
        "build": "webpack --mode development"  
      },  
      "keywords": [],  
      "author": "",  
      "license": "ISC",  
      "devDependencies": {  
        "css-loader": "^5.0.2",  
        "style-loader": "^2.0.0",  
        "file-loader": "^5.1.0",  
        "mini-css-extract-plugin": "^2.6.1"  
      }  
    }
    

    修改打包的配置文件01_webpackhello/webpack.config.js,这里将css打包到dist/css/img/main.css

    const path = require('path');  
    //step 1: 加载mini-css-extract-plugin  
    const MiniCssExtractPlugin = require('mini-css-extract-plugin');  
      
    module.exports = {  
        //这样,可以配置多个entry,同时打包多个文件  
        entry: {  
          main: './src/main.js',  
        },  
        output: {  
            path: path.resolve(__dirname, 'dist'),  
            filename: 'bundle.js'  
        },  
        module: {  
            rules: [  
                {  
                    test: /\.css$/i,  
                    //执行顺序从右向左,将css-loader处理后的结果传给MiniCssExtractPlugin.loader  
                    use: [MiniCssExtractPlugin.loader, 'css-loader'],  
                },  
                {  
                    test: /\.png$/,  
                    use: {  
                        loader: "file-loader",  
                        options: {  
                            name: 'css/img/[name].[ext]'  
                        }  
                    }  
                }  
            ],  
        },  
      
        //step 2: 创建mini-css-extract-plugin实例  
        plugins: [  
            new MiniCssExtractPlugin({  
                //指定css输出的文件  
                filename: 'css/[name].css'  
            })  
        ]  
    };
    

    修改测试的html文件01_webpackhello/index.html,引用前面打包的css:

    <html>  
    <head>  
        <!-- 引入打包生成的 JavaScript -->  
        <!--<script src="dist/bundle.js"></script>-->    <link rel="stylesheet" href="dist/css/main.css"/>  
    </head>  
    <body>  
    <h1 class="text-primary" id="hello_h1">Hello World</h1>  
    </body>  
    </html>
    

    在该目录下执行npm install命令,npm会自动根据package.json配置文件中的依赖进行新增安装mini-css-extract-plugin
    然后,执行npm run build命令,就可以执行打包操作。

    image.png

    ,在浏览器中打开前面新建的01_webpackhello/index.html,可以看到css已经生效,弹出alert框之后,字体显示为蓝色,并且有背景图片,如下。

    image.png

    3.4 使用asset modules处理图片文件

    asset modules是webpack5新加入的功能,称为资源模块,通过它,无需使用额外的预处理器,就可以将图片和字体等文件进行解析和处理。
    在上面例子的基础上,修改webpack打包的配置文件01_webpackhello/webpack.config.js,通过asset modules处理图片资源:

    const path = require('path');  
    //step 1: 加载mini-css-extract-plugin  
    const MiniCssExtractPlugin = require('mini-css-extract-plugin');  
      
    module.exports = {  
        //这样,可以配置多个entry,同时打包多个文件  
        entry: {  
          main: './src/main.js',  
        },  
        output: {  
            path: path.resolve(__dirname, 'dist'),  
            filename: 'bundle.js'  
        },  
        module: {  
            rules: [  
                {  
                    test: /\.css$/i,  
                    //执行顺序从右向左,将css-loader处理后的结果传给MiniCssExtractPlugin.loader  
                    use: [MiniCssExtractPlugin.loader, 'css-loader'],  
                },  
                {  
                    test: /\.png$/,  
                    type: 'asset/resource',  
                    generator: {  
                        filename: 'css/img/[name].[ext]'  
                    }  
                }  
            ],  
        },  
      
        //step 2: 创建mini-css-extract-plugin实例  
        plugins: [  
            new MiniCssExtractPlugin({  
                //指定css输出的文件  
                filename: 'css/[name].css'  
            })  
        ]  
    };
    

    执行npm run build命令,就可以执行打包操作。

    image.png

    ,在浏览器中打开前面新建的01_webpackhello/index.html,可以看到css已经生效,弹出alert框之后,字体显示为蓝色,并且有背景图片,如下。

    image.png

    参考资料

    相关文章

      网友评论

          本文标题:Webpack使用入门

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