按照webpack官網的說法,webpack本質上是javascript應用程序的靜態資源打包器(static module bundler),它能夠將模塊按照依賴和規則打包成符合生產環境部署的前端資源。webpack能夠將按模塊異步加載按需引用,經過loader的轉換還能夠將任何資源看做模塊,好比css、圖片、json、commonjs模塊、amd模塊、es6模塊等。現在webpack的大版本更新到4.x了,讓咱們看下如何使用。javascript
新建一個文件夾,依次執行:css
npm init
npm i webpack webpack-cli webpack-server -D
複製代碼
便可開始使用webpack。在文件夾中新建文件夾 src
、dist
和文件webpack.config.js
,其中 src
爲打包的源目錄用來存放咱們要打包的文件,dist
爲輸出目錄,webpack.config.js
是咱們配置webpack打包相關參數的文件。html
//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處理引入的模塊,支持的模塊類型有CoffeeScript,TypeScript,ES5/6,sass,less,stylus。模塊的依賴方式有:java
import
語句require()
語句define
和 require
語句@import
語句(url(...))
或 HTML 文件(<img src=...>)
中的圖片連接(image url)
下面我用一些loader來介紹module的用法,注意使用loader以前須要使用npm安裝對應的loader(npm i xxx-loader -D
)webpack
// 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官網上去尋找。git
另外還有一個圖片打包url-loader,須要注意它和file-loader的區別。url-loader能夠說是file-loader的進一步封裝,能夠將圖片轉換爲base64格式內聯在代碼中,這樣能夠減小圖片加載的http請求。es6
plugins也是webpack的重要功能之一,藉助插件咱們能夠實現loader沒法完成的工做。要使用插件以前,一樣須要使用npm安裝(npm i xxx -D
),而且在webpack.config.js中要引用該插件。下面我簡單介紹幾個插件的用法,想要更完整的資料能夠訪問webpack插件。github
// 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能夠在本地搭建一個webpack構建服務環境web
// 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
開啓服務,執行打包。
多文件打包的本質就是在入口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多頁面打包
原文連接:tech.gtxlab.com/webpack4.ht…
做者簡介: 宮晨光,人和將來大數據前端工程師。