webpack技術(shù)入門
webpack基本已經(jīng)成為前端項(xiàng)目的標(biāo)配構(gòu)建工具了。
然而,在一個(gè)前端團(tuán)隊(duì)里面,除了架構(gòu)師之外,其他開(kāi)發(fā)者很難有機(jī)會(huì)在工作中完整的實(shí)現(xiàn)整個(gè)配置流程。
本篇文章是我在公司里面分享webpack及babel配置和插件開(kāi)發(fā)的一個(gè)細(xì)節(jié)版本,
希望能讓大家通過(guò)閱讀本文,比較好的梳理webpack工具。
webpack的出現(xiàn)解決了什么問(wèn)題
JavaScript自面世之后,就成為瀏覽器的標(biāo)準(zhǔn)腳本語(yǔ)言。
然而JS本身并沒(méi)有提供python和java的package包、子模塊的import等語(yǔ)法。
同時(shí),前端代碼還需要處理類似CSS、png、webfonts等非JS的文件。
在前端工程化大潮下,一個(gè)既能處理JS又能處理別的資源文件的加載器(bundler)亟待出現(xiàn)。
webpack就是這類解決方案中的杰出代表。
下面,我將按照如下的目錄結(jié)構(gòu)對(duì)webpack使用進(jìn)行講解。
1、webpack概述
2、一個(gè)簡(jiǎn)單而通用的webpack配置文件
3、webpack的配置文件解讀
4、webpack常用的plugins及l(fā)oader
1.webpack概述
webpack = module building system。
在webpack看來(lái),所有的資源文件都是模塊(module),只是處理的方式不同。
上面兩句話就把webpack從top-level的角度講清楚了。
關(guān)于webpack的使用,其實(shí)和我們平時(shí)開(kāi)發(fā)業(yè)務(wù)產(chǎn)品是一個(gè)道理。
產(chǎn)品需求 ===> 代碼設(shè)計(jì) ===> 提供API給開(kāi)發(fā)者使用。
webpack解決的需求點(diǎn)就是如何更好的加載前端模塊。
這里我用了模塊二字,是因?yàn)閣ebpack從JS出發(fā),將所有的文件看做它要處理的模塊。
webpack本身并不關(guān)心這個(gè)模塊是什么,它只是調(diào)度配置文件中對(duì)模塊處理的方式來(lái)完成這一切,而不必糾結(jié)文件類型。
比如我們會(huì)在項(xiàng)目中使用ES6/7的語(yǔ)法來(lái)編寫JS代碼,
于是我們只需要配置babel-loader即可處理這種JS。
比如我們需要加載html文件獲取html字符串,
于是我們只需要配置raw-loader即可拿到對(duì)應(yīng)文件的字符串。
比如我們需要將sass/less文件預(yù)編譯成css,
于是我們只需要配置sass-loader/less-loader即可處理。
webpack提供了一套API接口,開(kāi)發(fā)者只需要按照它提供的規(guī)范照著做就行了。
對(duì)于開(kāi)發(fā)者來(lái)說(shuō),除了需要閱讀英語(yǔ)文檔能力和nodeJS之外,webpack的學(xué)習(xí)門檻真的不高。
2.一個(gè)簡(jiǎn)單而通用的webpack配置文件
我們以如下的 webpack.config文件來(lái)進(jìn)行分析
var webpack = require("webpack");
var DefinePlugin = require('webpack/lib/DefinePlugin');
module.exports = {
context:process.cwd(),
watch: true,
entry: './index.js',
devtool: 'source-map',
output: {
path: path.resolve(process.cwd(),'dist/'),
filename: '[name].js'
},
resolve: {
alias:{ jquery: process.cwd()+'/src/lib/jquery.js',}
},
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
_: 'underscore',
React: 'react'
}),
new DefinePlugin({
'process.env': {
'NODE_ENV': JSON.stringify('development')
}
})
],
module: {
loaders: [{
test: /\.js[x]?$/,
exclude: /node_modules/,
loader: 'babel-loader'
}, {
test: /\.less$/,
loaders:['style-loader', 'css-loader','less-loader']
}, {
test: /\.(png|jpg|gif|woff|woff2|ttf|eot|svg|swf)$/,
loader: "file-loader?name=[name]_[sha512:hash:base64:7].[ext]"
}, {
test: /\.html/,
loader: "html-loader?" + JSON.stringify({minimize: false })
} ]
}
};
這個(gè)簡(jiǎn)單的webpack配置文件,基本可以處理大多數(shù)的前端業(yè)務(wù)場(chǎng)景了。
通過(guò)配置plugins、module.loaders、entry、output基本可以構(gòu)建一個(gè)兼容本地開(kāi)發(fā)和生產(chǎn)環(huán)境的富應(yīng)用web工程,下面針對(duì)以上的配置文件進(jìn)行分析。
3. webpack的配置文件解讀
- module.loaders數(shù)組
[{
test: /\.js[x]?$/,
exclude: /node_modules/,
loader: 'babel-loader'
}]```
比如有個(gè)文件require('index.jsx'), webpack會(huì)根據(jù)文件名是否滿足test字段的正則來(lái)決定是否使用babel-loader來(lái)處理文件。 exclude則是告訴webpack不需要對(duì)node_modules目錄進(jìn)行處理
- resolve對(duì)象
resolve:{
alias:{ jquery:path.resolve(process.cwd(),'src/lib/jquery.js')},
extensions:['.js','.json']
}
resolve對(duì)象是在**webpack預(yù)編譯***時(shí)*,就加載進(jìn)整個(gè)webpack編譯的配置中的。
比如alias會(huì)建立文件標(biāo)識(shí)符映射表
require('jquery')==>require('/Users/**/src/lib/jquery.js')
- plugins數(shù)組
/** 比如有個(gè)文件代碼中存在process.env對(duì)象,則process.env將會(huì)被替換成上面的
{
'NODE_ENV': JSON.stringify('development')
} console.log(process.env)==>console.log(({"NODE_ENV":'development'}))
*/
plugins: [new DefinePlugin({
'process.env': {
'NODE_ENV': JSON.stringify('development')
}
})]
更進(jìn)一步的webpack配置含義可以參考我的github博客webpack編譯流程漫談**
4. webpack常用的loaders和plugins
關(guān)于loader這塊呢,webpack官方給出了非常詳盡的解決方案,基本不用開(kāi)發(fā)者再去開(kāi)源社區(qū)上尋找。前端資源loaders列表**
關(guān)于plugins這塊,除了webpack官方推薦的幾款plugins外,社區(qū)上也有非常多不錯(cuò)的插件。webpack內(nèi)置的plugins列表**
經(jīng)過(guò)多個(gè)前端項(xiàng)目搭建實(shí)踐下,筆者認(rèn)為如下幾款plugins是非常不錯(cuò)的。
1、代碼優(yōu)化之:
- CommonsChunkPlugin - 抽取公共代碼
- UglifyJsPlugin - 壓縮混淆代碼
2、 依賴注入之: - DefinePlugin - 自由變量注入
- ProvidePlugin - 模塊變量標(biāo)示符注入
3、 文件抽取之: - file-loader - 傳送font等文件
- ExtractTextPlugin - 抽取css文件
4、 開(kāi)發(fā)體驗(yàn)優(yōu)化之: - WebpackNotifierPlugin - 編譯完成動(dòng)態(tài)通知
- HtmlWebpackPlugin - 采用模板引擎形式注入到html文件,讓開(kāi)發(fā)更加easy
**5、 目錄/文件拷貝之:
CopyWebpackPlugin - 目錄及文件拷貝
5.webpack總結(jié)
本篇文章對(duì)webpack的講解主要集中在API層面。