這里介紹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目錄钻趋,并創(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;
}
//這里導出一個默認變量
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)境安裝
在當前目錄下執(zhí)行如下npm install
命令岗钩,npm會自動根據(jù)package.json配置文件中的依賴進行安裝纽窟。
$ npm install
up to date in 692ms
$
執(zhí)行完成后,這個目錄下會生成一個package-lock.json
配置文件兼吓,我們一般不用管它臂港。同時,前面在package.json中配置的依賴,應該會自動安裝到00_webpackhello/node_modules
目錄下审孽。
1.3 打包
在當前目錄下執(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
$
在當前目錄會新生成一個dist目錄县袱,其中包含打包生成的文件00_webpackhello/dist/bundle.js
。打包之后的完整目錄結(jié)構(gòu)如下圖佑力。
1.4 測試
這時候式散,如果在瀏覽器中打開前面創(chuàng)建的index.html,可以看到js已經(jīng)生效打颤。如下圖暴拄。
2、打包為js依賴庫
2.1 直接作為依賴庫引用報錯
前面的例子中编饺,如果在index.html中直接寫一個script標簽乖篷,調(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员寇,默認 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) { }
}));
// ===============================================
簡單說明見下圖:
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標簽中調(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丧失,也可以正常彈出豺妓,如下圖:
實際上,這樣打包之后布讹,也可以在單獨的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打包到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中马靠。它的原理很簡單,就是通過動態(tài)生成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,
//執(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配置文件中的依賴進行安裝抑胎。
然后燥滑,執(zhí)行npm run build
命令,就可以執(zhí)行打包操作圆恤。打包后的目錄結(jié)構(gòu)如下突倍。
這時候腔稀,在瀏覽器中打開前面新建的01_webpackhello/index.html
,可以看到css已經(jīng)生效羽历,彈出alert框之后焊虏,字體顯示為藍色,如下秕磷。
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,
//執(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配置文件中的依賴進行安裝。
然后签赃,執(zhí)行npm run build
命令谷异,就可以執(zhí)行打包操作。打包后的目錄結(jié)構(gòu)如下锦聊。
這時晰绎,在瀏覽器中打開前面新建的01_webpackhello/index.html
,可以看到css已經(jīng)生效括丁,彈出alert框之后荞下,字體顯示為藍色,并且有背景圖片史飞,如下尖昏。
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)如下纹份。
苟跪,在瀏覽器中打開前面新建的01_webpackhello/index.html
,可以看到css已經(jīng)生效蔓涧,彈出alert框之后件已,字體顯示為藍色,并且有背景圖片元暴,如下篷扩。
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,
//執(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配置文件中的依賴進行新增安裝mini-css-extract-plugin
。
然后值纱,執(zhí)行npm run build
命令鳞贷,就可以執(zhí)行打包操作。
虐唠,在瀏覽器中打開前面新建的01_webpackhello/index.html
搀愧,可以看到css已經(jīng)生效,彈出alert框之后疆偿,字體顯示為藍色咱筛,并且有背景圖片,如下杆故。
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,
//執(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í)行打包操作。
寝贡,在瀏覽器中打開前面新建的01_webpackhello/index.html
扒披,可以看到css已經(jīng)生效,彈出alert框之后圃泡,字體顯示為藍色碟案,并且有背景圖片,如下颇蜡。