Webpack使用入門

這里介紹webpack的基本使用。

1、打包js后引用

1.1 文件準(zhǔn)備

在一個單獨的目錄中新建配置文件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目錄,并創(chuàng)建待打包的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;  
}  
//這里導(dǎo)出一個默認(rèn)變量  
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 環(huán)境安裝

在當(dāng)前目錄下執(zhí)行如下npm install命令,npm會自動根據(jù)package.json配置文件中的依賴進(jìn)行安裝。

$ npm install

up to date in 692ms
$ 

執(zhí)行完成后,這個目錄下會生成一個package-lock.json配置文件,我們一般不用管它。同時,前面在package.json中配置的依賴,應(yīng)該會自動安裝到00_webpackhello/node_modules目錄下。

1.3 打包

在當(dāng)前目錄下執(zhí)行打包命令:

$ 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
$ 

在當(dāng)前目錄會新生成一個dist目錄,其中包含打包生成的文件00_webpackhello/dist/bundle.js。打包之后的完整目錄結(jié)構(gòu)如下圖。

image.png

1.4 測試

這時候,如果在瀏覽器中打開前面創(chuàng)建的index.html,可以看到j(luò)s已經(jīng)生效。如下圖。


image.png

2、打包為js依賴庫

2.1 直接作為依賴庫引用報錯

前面的例子中,如果在index.html中直接寫一個script標(biāo)簽,調(diào)用add函數(shù),如下:

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

會報錯add沒有定義。這是因為在javascript的模塊化語法里面,在每一個模塊文件中定義的函數(shù)和變量都是局部變量,所以,在模塊范圍之外沒法引用。

2.2 依賴庫打包配置說明

webpack支持將js文件打包為依賴庫,供其他人調(diào)用。通過library的配置可以支持指定庫的名稱, libraryTarget指定庫打包出來的規(guī)范。
其中,可選的值有“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,默認(rèn) 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標(biāo)簽中引用的依賴庫。
首先,修改打包的配置文件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標(biāo)簽中調(diào)用前面的依賴函數(shù),如下。

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

這樣,在00_webpackhello目錄下執(zhí)行npm run build打包命令之后,在瀏覽器中打開測試文件00_webpackhello/index.html,可以看到能夠正常被調(diào)用。第一個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文件中,也可以被調(diào)用到。

3、打包css

3.1 將css打包到j(luò)s中

3.1.1 預(yù)處理器css-loader和style-loader簡介

這里需要用到兩個預(yù)處理器css-loader和style-loader。css-loader的作用是解析css文件,包括解析@import等css自身語法,它會將解析后的css文件以字符串的形式打包到j(luò)s文件中(但此時,css樣式并不會生效,因為需要把css文件插入到html中才會生效)。style-loader的作用就是把js中的樣式代碼插入到html中。它的原理很簡單,就是通過動態(tài)生成style標(biāo)簽并將其插入到html文件的head標(biāo)簽中。

3.1.2 打包css到j(luò)s示例

在一個新的目錄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,  
                //執(zhí)行順序從右向左,將css-loader處理后的結(jié)果傳給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>

在該目錄下執(zhí)行npm install命令,npm會自動根據(jù)package.json配置文件中的依賴進(jìn)行安裝。
然后,執(zhí)行npm run build命令,就可以執(zhí)行打包操作。打包后的目錄結(jié)構(gòu)如下。

image.png

這時候,在瀏覽器中打開前面新建的01_webpackhello/index.html,可以看到css已經(jīng)生效,彈出alert框之后,字體顯示為藍(lán)色,如下。

image.png

3.2 處理css引入的圖片

3.2.1 file-loader簡介

file-loader是一個文件資源預(yù)處理器,作用是:處理文件導(dǎo)入語句(比如js的import ... from ...和css中的url())并替換成它的訪問地址,同時把文件輸出到相應(yīng)的位置。

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這幾個的版本號不配套,會導(dǎo)致一個圖片打包后生成兩個,其中一個還不能用的情況。
修改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,
               //執(zhí)行順序從右向左,將css-loader處理后的結(jié)果傳給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。
在該目錄下執(zhí)行npm install命令,npm會自動根據(jù)package.json配置文件中的依賴進(jìn)行安裝。
然后,執(zhí)行npm run build命令,就可以執(zhí)行打包操作。打包后的目錄結(jié)構(gòu)如下。

image.png

這時,在瀏覽器中打開前面新建的01_webpackhello/index.html,可以看到css已經(jīng)生效,彈出alert框之后,字體顯示為藍(lán)色,并且有背景圖片,如下。

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,
                //執(zhí)行順序從右向左,將css-loader處理后的結(jié)果傳給style-loader
                use: ['style-loader', 'css-loader'],
            },
            {
                test: /\.png$/,
                use: {
                    loader: "file-loader",
                    options: {
                        name: 'img/[name].[ext]'
                    }
                }
            }
        ],
    },
};

執(zhí)行npm run build命令,就可以執(zhí)行打包操作。打包后的目錄結(jié)構(gòu)如下。

image.png

,在瀏覽器中打開前面新建的01_webpackhello/index.html,可以看到css已經(jīng)生效,彈出alert框之后,字體顯示為藍(lán)色,并且有背景圖片,如下。

image.png

3.3 將css打包成到單獨的文件

還是前面的例子,代碼不變,修改打包的相關(guān)配置。
首先,修改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,  
                //執(zhí)行順序從右向左,將css-loader處理后的結(jié)果傳給MiniCssExtractPlugin.loader  
                use: [MiniCssExtractPlugin.loader, 'css-loader'],  
            },  
            {  
                test: /\.png$/,  
                use: {  
                    loader: "file-loader",  
                    options: {  
                        name: 'css/img/[name].[ext]'  
                    }  
                }  
            }  
        ],  
    },  
  
    //step 2: 創(chuàng)建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>

在該目錄下執(zhí)行npm install命令,npm會自動根據(jù)package.json配置文件中的依賴進(jìn)行新增安裝mini-css-extract-plugin。
然后,執(zhí)行npm run build命令,就可以執(zhí)行打包操作。

image.png

,在瀏覽器中打開前面新建的01_webpackhello/index.html,可以看到css已經(jīng)生效,彈出alert框之后,字體顯示為藍(lán)色,并且有背景圖片,如下。

image.png

3.4 使用asset modules處理圖片文件

asset modules是webpack5新加入的功能,稱為資源模塊,通過它,無需使用額外的預(yù)處理器,就可以將圖片和字體等文件進(jìn)行解析和處理。
在上面例子的基礎(chǔ)上,修改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,  
                //執(zhí)行順序從右向左,將css-loader處理后的結(jié)果傳給MiniCssExtractPlugin.loader  
                use: [MiniCssExtractPlugin.loader, 'css-loader'],  
            },  
            {  
                test: /\.png$/,  
                type: 'asset/resource',  
                generator: {  
                    filename: 'css/img/[name].[ext]'  
                }  
            }  
        ],  
    },  
  
    //step 2: 創(chuàng)建mini-css-extract-plugin實例  
    plugins: [  
        new MiniCssExtractPlugin({  
            //指定css輸出的文件  
            filename: 'css/[name].css'  
        })  
    ]  
};

執(zhí)行npm run build命令,就可以執(zhí)行打包操作。

image.png

,在瀏覽器中打開前面新建的01_webpackhello/index.html,可以看到css已經(jīng)生效,彈出alert框之后,字體顯示為藍(lán)色,并且有背景圖片,如下。

image.png

參考資料

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • webpack有什么作用? Webpack 是一個前端資源加載/打包工具,只需要相對簡單的配置就可以提供前端工程化...
    寧靜的夜閱讀 2,761評論 0 4
  • node安裝就自行百度吧! 確保你已經(jīng)進(jìn)入項目根目錄,npm init 創(chuàng)建 package.json 文件 we...
    ysp123閱讀 457評論 0 0
  • 前提:先安裝好nodejs,并配置好環(huán)境變量??梢匀质褂胣ode npm 命令 1. 初始化項目 新建一個目錄,...
    Kagari閱讀 863評論 0 0
  • 什么是webpack?我的理解是文件打包及資源處理,當(dāng)然功能肯定不局限于此。學(xué)習(xí)前提:了解npm,了解node.j...
    yozosann閱讀 1,801評論 2 15
  • webpack的主要功能 它提供了友好的前端模塊化開發(fā)的支持,以及代碼壓縮混淆、處理瀏覽器端javascript ...
    stamSuper閱讀 3,089評論 0 1

友情鏈接更多精彩內(nèi)容