簡介
按照webpack官網的說法,webpack本質上是javascript應用程式的靜態資源打包器(static module bundler),它可以將模組按照依賴和規則打包成符合生產環境部署的前端資源。webpack可以將按模組非同步載入按需引用,通過loader的轉換還可以將任何資源看作模組,比如css、圖片、json、commonjs模組、amd模組、es6模組等。如今webpack的大版本更新到4.x了,讓我們看下如何使用。
1.安裝使用
新建一個資料夾,依次執行:
npm init
npm i webpack webpack-cli webpack-server -D
複製程式碼
即可開始使用webpack。在資料夾中新建資料夾 src
、dist
和檔案webpack.config.js
,其中 src
為打包的源目錄用來存放我們要打包的檔案,dist
為輸出目錄,webpack.config.js
是我們配置webpack打包相關引數的檔案。
- 專案目錄
- webpack.config.js
//webpack.config.js
const path = require('path')
module.exports = {
// 打包模式,可選development和production
mode: 'development',
// 配置入口檔案
entry: './src/index.js',
// 配置輸出檔案
output: {
// 輸出路徑
path: path.resolve(__dirname, './dist'),
// 輸出檔名稱
filename: 'build.js'
},
// 模組,可以使用各種loader,比如css轉換,圖片壓縮等
module: {},
// 外掛,用於生成模板和其它功能
plugins: [],
// 可配置本地的webpack開發服務功能
devServer: {}
}
複製程式碼
編寫好webpack.config.js之後就使用命令npx webpack
開始執行打包了。webpack的打包機制,只能以js檔案為入口,如果你需要打包圖片,css,字型,svg等資源,必須使用es6或commonjs等模組載入規範在入口檔案中引入,否則是沒法進行打包構建的。
- module和一些loader的使用
module可以使用loader處理引入的模組,支援的模組型別有CoffeeScript,TypeScript,ES5/6,sass,less,stylus。模組的依賴方式有:
1.ES2015 import
語句
2. CommonJS require()
語句
3. AMD define
和 require
語句
4. css/sass/less 檔案中的 @import
語句
5. 樣式(url(...))
或 HTML 檔案(<img src=...>)
中的圖片連結(image url)
下面我用一些loader來介紹module的用法,注意使用loader之前需要使用npm安裝對應的loader(npm i xxx-loader -D
)
// webpack.config.js
module.exports = {
mode: '',
entry: '',
output: {},
module: {
rules: [
{
test: /\.css$/, // 匹配css檔案模組
use: ['style-loader', 'css-loader'] // 使用對應的loader處理
},
{
test: /\.(png|gif|jpe?g|svg)$/, // 匹配圖片檔案
use: [{
loader: 'file-loader',
options: {
name: '[path][name].[ext]?[hash]',
// 會輸出類似下面這樣的結果
// path/to/file.png?e43b20c069c4a01867c31e98cbce33c9
}
}]
},
{
test: /\.(html)$/, // 用來匹配html檔案模組(html需要通過外掛引入?),可以將html標籤中引入的圖片資源進行打包
use: [{
loader: 'html-loader',
options: {
attrs: ['<tag>:<attribute>'] // <tag>為引入圖片的標籤名,<attribute>為引入圖片的屬性名
}
}]
}
]
},
plugins: [],
devServer: {}
}
複製程式碼
通過上面例子中幾個loader的使用,大致的介紹了模組的作用和用法。如果沒有你需要的功能,可以去webpack官網上去尋找。
另外還有一個圖片打包url-loader,需要注意它和file-loader的區別。url-loader可以說是file-loader的進一步封裝,可以將圖片轉換為base64格式內聯在程式碼中,這樣可以減少圖片載入的http請求。
- plugins外掛的使用
plugins也是webpack的重要功能之一,藉助外掛我們可以實現loader無法完成的工作。要使用外掛之前,同樣需要使用npm安裝(npm i xxx -D
),並且在webpack.config.js中要引用該外掛。下面我簡單介紹幾個外掛的用法,想要更完整的資料可以訪問webpack外掛。
// webpack.config.js
const path = require('path')
// 使用外掛之前需要先載入對應的plugin
const CleanWebpackPlugin = require('clear-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')
module.exports = {
mode: '',
entry: {
a: './src/a.js', // 可以引入多個入口檔案
b: './src/b.js'
},
output: {
path: path.resolve(__dirname + '/dist/'),
filename: '[name].[hash:8].js' // 輸出多個結果,檔名帶hash值
},
module: {},
plugins: [
// 每次構建完成後先清理一遍dist目錄
new CleanWebpackPlugin(['dist']),
// 生成html檔案到輸入目錄
new HtmlWebpackPlugin({
// 可以以src目錄下的html原始檔為模板
template: './src/index.html',
// 在目標目錄下生成目標檔案
filename: './dist/index.html',
chunks: ['a', 'b'] // 這個引數配合entry可以將打包的模組以<script></script>的形式載入到html檔案中
}),
// 該外掛可以將源目錄中的檔案直接複製到目標目錄中
new CopyWebpackplugin([{
from: './src/*.css', // 選擇源目錄下的所有css檔案
flatten: true // 選擇拷貝檔案還是包括資料夾,預設是false
}])
],
devServer: {}
}
複製程式碼
- devServer
devServer可以在本地搭建一個webpack構建服務環境
// webpack.config.js
module.exports = {
mode: '',
entry: {},
output: {},
module: {},
plugins: [],
devServer: {
contentBase: '/dist', // 服務的內容目錄
port: 4396, // 搭建在本地的服務的埠號
compress: true, // 服務開啟gzip壓縮
open: true // 自動開啟本地瀏覽器
}
}
複製程式碼
同時將專案目錄下的package.json改寫一下。
// package.json
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "webpack-dev-server", // 開啟本地的webpack開發服務環境
"build": "webpack" // 執行打包
}
複製程式碼
之後我們就可以執行npm run start
、npm run webpack
開啟服務,執行打包。
2.多檔案入口打包
多檔案打包的本質就是在入口entry新增多個打包入口,在上面介紹plugins的HtmlWebpackPlugins時就用到了兩個入口。我們自然而然的想到有多少個入口檔案,就在entry裡面新增幾個入口不就好了。這樣雖然可以實現多檔案打包,但是每次我們新加一個入口都要手動新增,非常麻煩。所以我們想辦法匹配獲取到源目錄下的所有的入口檔案,然後新增到entry中即可。
function getEntry () {
let globPath = 'src/**/*.html' // 匹配src目錄下的所有資料夾中的html檔案
// (\/|\\\\) 這種寫法是為了相容 windows和 mac系統目錄路徑的不同寫法
let pathDir = 'src(\/|\\\\)(.*?)(\/|\\\\)' // 路徑為src目錄下的所有資料夾
let files = glob.sync(globPath)
let dirname, entries = []
for (let i = 0; i < files.length; i++) {
dirname = path.dirname(files[i])
entries.push(dirname.replace(new RegExp('^' + pathDir), '$2').replace('src/', ''))
}
return entries
}
function addEntry () {
let entryObj = {}
getEntry().forEach(item => {
entryObj[item] = resolve(__dirname, 'src', item, 'index.js')
})
return entryObj
}
複製程式碼
通過上面兩個方法我們就能獲取到src目錄下的所有入口檔案。下面我們看webpack.config.js如何修改
// ...
{
// entry: resolve(__dirname, "src/home/index.js")
// 改為
entry: addEntry()
//...
}
// ...
getEntry().forEach(pathname => {
let conf = {
filename: pathname.replace('src/', '') + '.html',
template: path.join(__dirname, 'src', pathname, 'index.html'),
chunks: Array.call([], pathname)
}
webpackconfig.plugins.push(new HtmlWebpackPlugin(conf))
})
複製程式碼
這樣我們就能夠實現自動的匹配所有入口檔案和要生成的html模板檔案,同時在HtmlWebpackPlugin外掛使用時,也自動新增了多個模板入口,在目標目錄下生成多個html檔案。
上面只是大致介紹了多入口的思路,具體程式碼可以看我實現的一個demo多頁面打包
參考文章
作者簡介: 宮晨光,人和未來大資料前端工程師。