包html需要用到一個插件html-webapck-plugin。
npm i html-webpack-plugin -D
package.json需要的開發(fā)依賴如下:
{
"name": "wpk5-demo",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"html-webpack-plugin": "^5.3.1",
"webpack": "^5.28.0",
"webpack-cli": "^4.5.0"
}
}
webpack.config.js的配置如下:
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/main.js',
output: {
filename: 'bundle.js',
path: resolve(__dirname, 'dist')
},
module: {
rules: []
},
plugins: [
new HtmlWebpackPlugin({
template: './src/assets/index.html',
hash: true,
filename: 'index.html',
favicon: './src/assets/favicon.ico'
})
],
mode: 'development'
}
代碼倉庫:https://gitee.com/seimin/xiaoming2qianduan-webpack5/tree/v5.1/
語
在最近的項(xiàng)目開發(fā)中,涉及到了多頁面的 webpack 打包,以下是我項(xiàng)目過程中的一些踩坑總結(jié)。
前言
項(xiàng)目使用了 vue 作為框架來開發(fā)前端頁面,其中需要開發(fā)多個前端頁面,包括有登錄、進(jìn)游戲、充值等等。作為vue最佳的打包工具—— webpack,需要將各個頁面分別打包到不同模板目錄里。
但默認(rèn)的 vue 項(xiàng)目框架是單頁面應(yīng)用的,并不能達(dá)到項(xiàng)目開發(fā)的目的。這就需要調(diào)整 webpack 的配置來實(shí)現(xiàn)多頁面的發(fā)布處理。
以下是目錄結(jié)構(gòu):
project
├───bin
│ └───vb.js
├───build
│ │ dev.js
│ │ release.js
│ │ webpack.config.base.js
│ │ webpack.config.build.js
│ └───webpack.config.dev.js
│ README.md
│ package.json
└───src
├───components
│ │ count.vue
│ │ dialog.vue
│ │ errortips.vue
│ └───...
├───game
│ │ game.htm
│ │ game.js
│ └───game.vue
├───login
│ │ login.htm
│ │ login.js
│ └───login.vue
├───pay
│ │ pay_result.htm
│ │ pay_result.js
│ │ pay_result.vue
│ │ pay.htm
│ │ pay.js
│ └───pay.vue
└───...
修改配置前的一些知識
我們知道webpack的核心是一切皆模塊,所以它本質(zhì)上是一個靜態(tài)模塊打包器。當(dāng) webpack 處理應(yīng)用程序時,它會遞歸地構(gòu)建一個依賴關(guān)系圖,其中包含應(yīng)用程序需要的每個模塊,然后將所有這些模塊打包成一個或多個 bundle。
官網(wǎng)顯示的這幅圖很形象地描述了這個過程。
從 webpack v4.0.0 開始,webpack 提供了一系列的配置默認(rèn)項(xiàng),讓開發(fā)者可以零配置打包,不再強(qiáng)制要求必須進(jìn)行繁瑣的 webpack 配置,讓開發(fā)者可以從繁瑣的配置文件里抽出,專注應(yīng)用的開發(fā)。但是若你需要有特殊的處理,webpack 仍然可以進(jìn)行高度可配置來滿足你的需求。
在開始前需要了解四個核心概念:
本篇將會針對這4個核心配置的修改和優(yōu)化來實(shí)現(xiàn)多頁面打包。在 webpack4 的版本,還新增了一個 mode 配置項(xiàng)。mode 有兩個值:development 或者是 production,用戶可以啟用相應(yīng)模式下的 webpack 內(nèi)置的優(yōu)化。不同 mode 的區(qū)別與默認(rèn)配置可以參考:https://segmentfault.com/a/1190000013712229
一、入口配置
在單頁面應(yīng)用里,一般在根目錄下面會有一個 index.html 文件。它是頁面的 html 模板文件。但是在多頁面應(yīng)用里,則會有多個應(yīng)用模板文件,為了方便管理,可以將不同類的入口文件、邏輯處理和模板文件分別存放在相應(yīng)的獨(dú)立目錄。若用到了組件,則單獨(dú)將組件存放在一個目錄。
project
└───src
├───components
│ │ count.vue
│ │ dialog.vue
│ │ errortips.vue
│ └───...
├───game
│ │ game.htm
│ │ game.js
│ └───game.vue
├───login
│ │ login.htm
│ │ login.js
│ └───login.vue
├───pay
│ │ pay_result.htm
│ │ pay_result.js
│ │ pay_result.vue
│ │ pay.htm
│ │ pay.js
│ └───pay.vue
└───...
webpack 的入口配置中是支持多入口的,給 entry 傳入對象即可,如下所示:
const config = {
entry: {
game: './src/game/game.js',
login: './src/login/login.js',
pay: './src/pay/pay.js',
pay_result: './src/pay/pay_result.js'
}
};
但這樣的配置對于未知頁面數(shù)量的項(xiàng)目并不友好,若每新增頁面都要重新配置和重啟程序,顯然是不合理的。而我們可以創(chuàng)建一個getEntry()的方法來遍歷文件夾來獲取入口。
const fs = require('fs');
const glob = require("glob");
function getEntry() {
const entry = {};
//讀取src目錄所有page入口
glob.sync('./src/*/*.js') //獲取符合正則的文件數(shù)組
.forEach(function (filePath) {
var name = filePath.match(/\/src\/(.+)\/*.js/);
name = name[1];
//須有配套的模板文件才認(rèn)為是入口
if (!fs.existsSync('./src/' + name + '.htm')) {
return;
}
entry[name] = filePath;
});
return entry;
};
module.exports = {
// 多入口
entry: getEntry(),
}
二、輸出配置
輸出配置僅需指定一個
const config = {
output: {
path: path.join(__projectDir, __setting.distJs),
publicPath: __setting.domainJs, //自定義變量,用來定義公共靜態(tài)資源路徑
filename: '[name][hash].js'
},
};
https://www.webpackjs.com/configuration/output/#output-publicpath
https://www.webpackjs.com/configuration/output/#output-filename
在配置中有以下幾點(diǎn)需要注意:
publicPath 是指定在瀏覽器中所引用的「此輸出目錄對應(yīng)的公開 URL」。
簡單的例子:
publicPath: "https://cdn.example.com/assets/"
輸出到html則變成
<script src="https://cdn.example.com/assets/bundle.js"></script>
這個屬性是整個項(xiàng)目共用的靜態(tài)資源路徑,若某個模塊需要使用其他的靜態(tài)資源路徑。webpack 提供了__webpack_public_path__來動態(tài)設(shè)置 publicPath,只需在入口文件的最頂部定義即可。
__webpack_public_path__ = myRuntimePublicPath; // 一定要寫在最頂部
filename的[hash]是以項(xiàng)目為維度的 hash 值,若輸出了多個文件,則文件名都會共用一個 hash 值。
filename的[chunkhash]是以chunk為維度生成的 hash 值,不同入口生成不同的 chunkhash 值。
filename的[contenthash]根據(jù)資源內(nèi)容生成的 hash 值。
通常使用 hash 或 chunkhash,contenthash 通常用于某些特殊場景(官方文檔在使用 ExtractTextWebpackPlugin 插件時有使用)。
https://www.webpackjs.com/plugins/extract-text-webpack-plugin/
三、loader配置
由于 webpack 只能理解 JavaScript 和 JSON 文件。而配置 loader 就是讓 webpack 能夠去處理其他類型的文件,并將它們轉(zhuǎn)換為有效模塊。
loader 可以使開發(fā)者在 import 或"加載"模塊時預(yù)處理文件。例如,將內(nèi)聯(lián)圖像轉(zhuǎn)換為 data URL,或者允許開發(fā)者直接在 JavaScript 模塊中 import CSS文件
1、js 模塊
加載js模塊,我們通常是為了引入babel,讓其能將ES6的語法轉(zhuǎn)成ES5,讓項(xiàng)目能在低版本的瀏覽器上運(yùn)行。
js文件需要使用babel的話,引入babel-loader
const config = {
module: {
rules: [{
test: /\.js$/,
include: [path.resolve(__projectDir, 'src')], //通過include精確指定只處理哪些目錄下的文件
exclude: /node_modules/, //設(shè)置哪些目錄里的文件不進(jìn)行處理
loader: "babel-loader"
}]
}
}
但僅僅配置了babel-loader還不夠,還需要配置 babel 的環(huán)境,需要引入 polyfill。
引入 polyfill 的方式有很多種,根據(jù) vue 官方文檔在瀏覽器兼容性的處理,默認(rèn)使用的是@vue/babel-preset-app ,它通過@babel/preset-env和browserslist配置來決定項(xiàng)目需要的 polyfill。
https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/babel-preset-app
browserslist
項(xiàng)目根目錄創(chuàng)建.browserslist文件
> 1%
last 2 versions
當(dāng)然,你也可以在package.json文件里添加的browserslist字段來配置。
這個配置的目的是為了指定了項(xiàng)目的目標(biāo)瀏覽器的范圍,配置的值會被 @babel/preset-env 用來確定需要轉(zhuǎn)譯的 JavaScript 特性。
詳細(xì)的說明可以查閱 https://github.com/browserslist/browserslist,了解如何指定瀏覽器范圍。
Polyfill
項(xiàng)目根目錄創(chuàng)建.babelrc文件
{
"presets": [
["@babel/preset-env",
{
"modules": false, // 對ES6的模塊文件不做轉(zhuǎn)化,以便使用tree shaking、sideEffects等
"useBuiltIns": "entry", // browserslist環(huán)境不支持的所有墊片都導(dǎo)入
"corejs": {
"version": 3, // 使用core-js@3
"proposals": true
}
}
]
]
}
這里特別說下的是配置里的useBuiltIns,可設(shè)置的值分別是"usage" | "entry" | false,3個值分別代表:
項(xiàng)目使用的是"useBuiltIns": "entry",所以需要指定corejs的版本,這里使用的版本是core-js@3,所以我們在 webpack 的入口配置里加上"core-js/stable"和 "regenerator-runtime/runtime"。
function getEntry() {
const entry = {};
//讀取src目錄所有page入口
glob.sync('./src/*/*.js') //獲取符合正則的文件數(shù)組
.forEach(function (filePath) {
var name = filePath.match(/\/src\/(.+)\/*.js/);
name = name[1];
//須有配套的模板文件才認(rèn)為是入口
if (!fs.existsSync('./src/' + name + '.htm')) {
return;
}
entry[name] = ["core-js/stable", "regenerator-runtime/runtime", path.join(__projectDir, filePath)];
});
return entry;
};
2、css 模塊
我們通常使用style-loader和css-loader。css-loader用來處理 js 文件中引入的 css 模塊(處理@import和url()),style-loader是將css-loader打包好的css代碼以<style>標(biāo)簽的形式插入到 html 文件中。而 webpack 對于 loader 的調(diào)用是從右往左的,所以通常是這樣配置:
{
test: /\.css$/,
use: [ 'style-loader', 'css-loader' ]
}
我們在項(xiàng)目中還經(jīng)常會使用 sass 或者 scss。sass 是一種 CSS 的預(yù)編譯語言。因此 webpack 要將其處理會使用更多 loader。
{
test: /\.(sc|sa)ss$/,
use: [{
loader: 'vue-style-loader'
}, {
loader: 'css-loader',
options: {
sourceMap: true,
}
}, {
loader: 'postcss-loader',
options: {
sourceMap: true
}
}, {
loader: 'sass-loader',
options: {
sourceMap: true
}
}, {
loader: 'sass-resources-loader', //組件里面使用全局scss
options: {
sourceMap: true,
resources: [
path.resolve('./src/public/css/common.scss')
]
}
}]
}
在使用sass-loader的時候若某個 scss 文件(比如a.scss)@import 了其他 scss 文件(比如b.scss),如果b.scss里的url()的路徑是相對路徑,在sass-loader處理過后給css-loader處理時就會報錯,找不到url()里指定的資源。
這是因?yàn)閟ass-loader處理時,會將 scss 文件里 @import 路徑的文件一并合并進(jìn)來,結(jié)合上面的例子就是b.scss會被sass-loader合并進(jìn)a.scss。
如何解決呢?可以有兩個解決方法:
在項(xiàng)目中由于還用到了postcss-loader,我們還須要在根目錄創(chuàng)建postcss-loader的配置文件postcss.config.js
//自動添加css瀏覽器前綴
module.exports = {
plugins: [
require('autoprefixer')
]
}
3、圖片等靜態(tài)資源
對于圖片資源的打包,經(jīng)常會使用file-loader來完成,配置也很簡單:
{
test: /\.(gif|png|jpe?g)$/,
loader: 'file-loader',
}
打包后,會將圖片移動到了 dist 目錄下,并將該圖片改名為[hash].[ext]格式的圖片。開發(fā)者也可以根據(jù)需要,修改輸出的文件名。
但在項(xiàng)目開發(fā)過程中,我們會創(chuàng)建很多張圖片,這就使得頁面在加載是時候會發(fā)送很多http請求,當(dāng)頁面圖片過多,會影響的頁面的性能。所以,這里推薦使用url-loader。
{
test: /\.(png|jpg|jepg|svg|gif)$/,
use: [{
loader: 'url-loader',
options: {
limit: 10240, //這里的單位是b
name: 'image/[name][hash].[ext]' //打包后輸出路徑
}
}]
}
使用url-loader我們可以通過設(shè)置limit的值,將文件大小小于某個值的圖片打包成base64的形式存放在打包后的 js 中,若超過了這個設(shè)定值,默認(rèn)會使用file-loader(所以雖然代碼沒有配置 file-loader,但還是需要使用安裝file-loader),并且會將配置的選項(xiàng)傳遞給file-loader。
4、import AMD 模塊
有時我們需要在項(xiàng)目里使用一些 AMD 模塊或者完全不支持模塊化的庫。例如移動端經(jīng)常使用的 zepto。如果我們直接使用 import zepto 的方式引入是會報錯的:Uncaught TypeError: Cannot read property 'createElement' of undefined
要使用也很簡單,使用script-loader和exports-loader即可:
{
test: require.resolve('zepto'),
use: ['exports-loader?window.Zepto','script-loader']
}
四、plugins
webpack 可以使用插件(plugins)來讓開發(fā)者能夠在打包的過程中實(shí)現(xiàn)更多功能,插件會在整個構(gòu)建過程中生效,并執(zhí)行相關(guān)的任務(wù)。這里會介紹幾個比較實(shí)用的插件:
1、mini-css-extract-plugin
在使用style-loader處理后,css 文件會作為模塊打包進(jìn) js 文件里。若我們想將 js 文件和 css 文件分離。就可以使用mini-css-extract-plugin:
module: {
rules: [{
test: /\.css$/,
use: [{
loader: MiniCssExtractPlugin.loader
},
'css-loader'
]
}]
},
plugins: [
new MiniCssExtractPlugin({
filename: 'css/[hash].css'
})
]
2、copy-webpack-plugin
有時候我們會有一些沒經(jīng)過打包的文件需要復(fù)制到我們的生產(chǎn)目錄里,copy-webpack-plugin就可以實(shí)現(xiàn)這個功能。
plugins: [
new CopyWebpackPlugin([
{
from: { glob: './src/public/*.htm', dot: true },
to: path.join(__setting.distTpl, 'public','[name].htm')
}
], { copyUnmodified: true })
]
3、html-webpack-plugin
我們前面介紹入口配置的時候會看到只配置了 js 文件,只是因?yàn)?webpack 現(xiàn)在入口只支持 js 文件,所以打包輸出的也是 js 文件,那如果我們需要將 js 文件引入到 html 里,就需要使用到html-webpack-plugin插件。
html-webpack-plugin在使用的時候,是必須一個入口對應(yīng)一個配置的,所以我們前面使用了多頁面的配置,也需要進(jìn)行相應(yīng)的修改,修改后的getEntry方法:
const htmlPluginArray = [];
function getEntry() {
const entry = {};
//讀取src目錄所有page入口
glob.sync('./src/' + __setting.moduleId + '/*.js')
.forEach(function (filePath) {
var name = filePath.match(/\/src\/(.+)\/*.js/);
name = name[1];
if (!fs.existsSync(path.join(__projectDir, './src/' + name + '.htm'))) {
return;
}
entry[name] = ["core-js/stable", "regenerator-runtime/runtime", path.join(__projectDir, filePath)];
+ htmlPluginArray.push(new HtmlWebpackPlugin({
+ filename: `${__setting.distTpl}/${name}.htm`,
+ template: './src/' + name + '.htm',
+ inject: 'body',
+ minify: {
+ removeComments: true,
+ collapseWhitespace: true
+ },
+ chunks: [name],
+ inlineSource: '.(js|css)'
+ }))
});
return entry;
};
// 配置plugin,由于plugins通常使用數(shù)組類型來配置,
// 所以可以使用concat方法將配置好的html的數(shù)組添加進(jìn)去。
plugins: [
new MiniCssExtractPlugin({
filename: 'css/[hash].css'
})
].concat(htmlPluginArray),
里面的一些配置是要注意一下的:
filename 是配置需要將 html 改成什么名字并輸出到哪里的配置。這里配置的的路徑是以 output 里配置的path為相對路徑的,我們上面 output 配置的是
path: path.join(__projectDir, __setting.distJs)
那最終的html輸出路徑就是
path.join(__projectDir, __setting.distJs,
`${__setting.distTpl}/${name}.htm`)
是將html里的代碼進(jìn)行壓縮。如果 minify 選項(xiàng)設(shè)置為 true 或者配置對象 ( true 是 webpack 模式為 production 時的默認(rèn)值),生成的 HTML 將使用 HTML-minifier壓縮代碼,更多具體的配置可以看這里minification。
template 生成 filename 文件的模版。重點(diǎn):與 filename 的路徑不同, 當(dāng)匹配模版路徑的時候?qū)捻?xiàng)目的根路徑開始。
inject 制定 webpack 打包的 js css 靜態(tài)資源插入到 html 的位置。
chunks 指定模板允許添加哪個入口文件。若不配置這個會將所有的入口都添加進(jìn)來。
4、html-webpack-inline-source-plugin
若我們想將打包好的 js 代碼 inline 進(jìn) html 的話,就要使用到html-webpack-inline-source-plugin
可以看到上面html-webpack-plugin的配置里有inlineSource: '.(js|css)'
這就是告訴html-webpack-inline-source-plugin需要將打包好的代碼 inline 進(jìn) html 里,插件需要添加到html-webpack-plugin的配置后
plugins: [
new MiniCssExtractPlugin({
filename: 'css/[hash].css'
})
].concat(htmlPluginArray).concat([
new HtmlWebpackInlineSourcePlugin()
])
但是html-webpack-inline-source-plugin也僅能將打包后輸出的 js 文件引入 html,若你想將 html 碼其他使用 script 標(biāo)簽加載的 js 文件或者 style 標(biāo)簽加載的 css 文件也 inline 進(jìn) html 里的話,html-webpack-inline-source-plugin并不能實(shí)現(xiàn)。從html-webpack-plugin里的 Issues 來看,html-webpack-plugin的作者也無意做這樣的事情,但也給出了建議,可以借助html-webpack-plugin插件的 hooks html-webpack-plugin-before-html-processing達(dá)到我們需要的效果。
5、自定義插件
上面說到要將外部的靜態(tài)文件也 inline 進(jìn) html,我們可以編寫自定義插件,借助html-webpack-plugin插件的 hooks html-webpack-plugin-before-html-processing,再結(jié)合inline-source組件來實(shí)現(xiàn)我們的功能。
const {
inlineSource
} = require('inline-source');//加載inline-source組件
//定義方法
function scriptInlineHtml(options) {
// Configure your plugin with options...
this.options = options || {};
}
scriptInlineHtml.prototype.apply = function (compiler) {
let that = this;
(compiler.hooks ? //判斷webpack版本,4.0以上和4.0以下的處理不一樣
compiler.hooks.compilation.tap.bind(compiler.hooks.compilation, 'script-inline-html') :
compiler.plugin.bind(compiler, 'compilation'))(function (compilation) {
(compilation.hooks ?
compilation.hooks.htmlWebpackPluginBeforeHtmlProcessing.tapAsync.bind(compilation.hooks.htmlWebpackPluginBeforeHtmlProcessing, 'script-inline-html') :
compilation.plugin.bind(compilation, 'html-webpack-plugin-before-html-processing'))(async function (htmlPluginData, callback) {
//獲取的html內(nèi)容處理后重新賦值;
try {
htmlPluginData.html = await inlineSource(htmlPluginData.html, that.options);
// Do something with html
} catch (err) {
// Handle error
}
//繼續(xù)執(zhí)行下個插件
callback(null, htmlPluginData);
});
});
};
//webpack插件添加
plugins: [
new MiniCssExtractPlugin({
filename: 'css/[hash].css'
})
].concat(htmlPluginArray).concat([
new scriptInlineHtml(),
new HtmlWebpackInlineSourcePlugin()
])
使用
<script src="/src/public/js/px2rem.js" inline></script>
這里結(jié)合 inline 靜態(tài)資源,簡單介紹了自定義插件的使用,在html-webpack-plugin構(gòu)建 html 過程中,還提供其他一系列的事件。
Async:
Sync:
這些事件可以讓我們在構(gòu)建 html 的不同階段里,通過一些處理來達(dá)到我們的目的。例如:可以結(jié)合smarty.js將使用了 smarty 的模板,引入一些模擬數(shù)據(jù)后解析成正常的html代碼;讀取 HTML 文件進(jìn)行翻譯文本的替換,實(shí)現(xiàn)頁面的多語言化。打包不同皮膚的html文件等等。
五、其他配置
1、resolve
resolve 配置規(guī)定了 webpack 如何尋找各個依賴模塊。
前面有講到使用 alias 設(shè)置路徑別名。在資源引用時,如果資源引用路徑太深,又比較常用,我們可以定義路徑別名,例如:
resolve: {
alias: {
'@': path.resolve(__projectDir, 'src')
}
}
我們就可以直接在代碼中這樣引用了:
let backimg = require("@/public/image/common/ico-back.png").default;
2、webpack dev server
webpack-dev-server是開發(fā)時的必備利器,它可以在本地起一個簡單的 web 服務(wù)器,當(dāng)文件發(fā)生變化時,能夠?qū)崟r重新加載。webpack-dev-server的配置也很簡單:
devServer: {
contentBase: __projectDir, //頁面的基礎(chǔ)目錄
publicPath:'/',
port: 8080,
host: '127.0.0.1',
open: true, //是否運(yùn)行后自動打開瀏覽器
hot: true
}
啟動 webpack-dev-server 后,在目標(biāo)文件夾中是看不到編譯后的文件的,實(shí)時編譯后的文件都保存到了內(nèi)存當(dāng)中。
1) HMR
hot設(shè)置為 true 是啟用 webpack 的 模塊熱替換( HMR )功能,但這里注意必須要添加插件webpack.HotModuleReplacementPlugin 才能完全啟用 HMR
2) publicPath
publicPath 路徑下的打包文件可以在瀏覽器中訪問,webpack-dev-server 打包的內(nèi)容是放在內(nèi)存中的,并沒有實(shí)際創(chuàng)建文件,這些打包后的資源對外的的根目錄就是 publicPath。
默認(rèn) devServer.publicPath 是 '/',所以你的包( bundle )可以通過 http://127.0.0.1:8080/bundle.js 訪問。注意:當(dāng)這里的 publicPath 和 output 的 publicPath 同時設(shè)置時,這里的優(yōu)先級更高。
總結(jié)
webpack 的配置能介紹的點(diǎn)其實(shí)還有很多,例如開發(fā)環(huán)境和生產(chǎn)環(huán)境進(jìn)行配置分離;利用瀏覽器的緩存將公共的模塊抽離分開打包;還有很多常用 plugins 插件等等。
這篇文章是以我在開發(fā)某個多頁面應(yīng)用項(xiàng)目為例,總結(jié)了一些我在webpack配置上的理解。希望能對瀏覽這篇文章的小伙伴有幫助。
作者:HZH
來源-微信公眾號:三七互娛技術(shù)團(tuán)隊(duì)
出處:https://mp.weixin.qq.com/s/JzZDqe-f_NRMmdxDLXC7tQ
webpack是一個js/css打包模塊的機(jī)制,它可以識別代碼中的依賴關(guān)系進(jìn)行打包編譯,生成代碼,頁面只需引入編譯好的js代碼文件即可。
webpack是nodejs的一個模塊,所以需要先安裝nodejs才能使用
webpack可以實(shí)現(xiàn)模塊化管理,你可以寫很多簡單的js方法,通過組裝形成各種功能,使js代碼更加靈活,避免重復(fù)性勞動。
1.下載安裝nodejs
2.安裝nodejs包管理器
npm install
3.新建源文件src/index.js
4.手動打包
npx webpack --entry=./src/index.js --output-filename=bundle.js --mode=development
*請認(rèn)真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。