什么是webpack
webpack是一個模塊打包的解決方案
webpack和gulp對比
其實沒啥可比性誓竿,gulp是構(gòu)建前端自動化流程的工具栗竖,而webpack只是一個模塊打包的。gulp可以制定一些任務(wù)吧黄,自動執(zhí)行一些操作肺魁。webpack是通過一個給定的入口主文件添瓷,然后將這個主文件內(nèi)的所有依賴的文件都用loaders處理,最后打包成一個瀏覽器可以識別的js文件痢士。webpack的處理速度更快彪薛,它把所有文件都當(dāng)做模塊處理,css以及圖片等等怠蹂。
基礎(chǔ)的配置文件
module.exports = {
context:__dirname+"/app"
entry: "./main.js",//唯一入口文件
output: {
path: __dirname + "/public",//打包后的文件存放的地方善延,相對
filename: "bundle.js"http://打包后輸出文件的文件名
//publicPath:'http://cdn' 一般通過比如cdn加載網(wǎng)絡(luò)靜態(tài)資源,作為前綴路徑城侧,一般生產(chǎn)環(huán)境會用這個替換路徑
}
}
注意挚冤,“__dirname”是node.js中的一個全局變量,它指向當(dāng)前執(zhí)行腳本所在的目錄赞庶。
當(dāng)entry為數(shù)組或?qū)ο?/h3>
當(dāng)有多個入口vendor和index的時候训挡,會分別從多個入口內(nèi)進(jìn)入,并掃描全部依賴生成一個vendor.js和index.js文件
module.exports = {
entry:{
"vendor":['jquery','abc.js'],
"index":'./public/src/index.js',
},
output:{
path:'/public',
filename:"[name].js" //vendor.js,index.js
}
}
更快捷的執(zhí)行打包
有時候我們需要執(zhí)行webpack —watch —xxx-xx等一系列很長的命令時歧强,這樣去敲是不太方便的澜薄,我們可以將長命令配置在package.json中,通過npm腳本執(zhí)行摊册。
{
"name": "webpack_demo",
"version": "1.0.0",
"description": "webpack_demo",
"scripts": {
"abc": "webpack xxx xxx xxx" //在此處配置肤京,相當(dāng)于把npm run abc替換成了webpack xxx
},
}
Source Maps方便調(diào)試
打包后文件出錯往往找不到對應(yīng)的源代碼位置,Source Maps就是用來解決這個問題的,他可以幫我們映射編譯文件對應(yīng)源文件的位置忘分。
module.exports = {
// 注意棋枕,source map有多種,下面這種是比較合適的
devtool:'eval-source-map',//配置生成Source Maps妒峦,
entry:__dirname + "/app/main.js",
output:{
path:__dirname + "/public",
filename:"bundle.js"
}
}
webpack構(gòu)建本地服務(wù)器
通過安裝webpack-dev-server的模塊重斑,然后配置devserver來開啟本地服務(wù)器,它可以讓瀏覽器檢測代碼修改肯骇,并自動刷新頁面顯示修改后的結(jié)果窥浪,它是基于node.js構(gòu)建的。
module.exports = {
devServer:{
contentBase:"./public", //本地服務(wù)器所加載的頁面所在的目錄
colors:true, //終端中輸出結(jié)果為彩色
historyApiFallback:true, //不跳轉(zhuǎn)
inline:true //實時刷新
}
}
resolve
用來控制搜索路徑笛丙,平常引用文件的時候路徑比較長漾脂,比如./app/src/components
,現(xiàn)在我們可以用一個別名代替
module.exports = {
resolve:{
//默認(rèn)從此處開始搜索模塊
root:[
path.join(__dirname,"node_modules")
],
//別名
alias:{
js:path.join(_dirname,"../app/src/scripts")
},
//擴(kuò)展文件名后綴胚鸯,require模塊的時候可以不寫后綴名
extensions: ['', '.js', '.vue', '.scss', '.css']
}
}
現(xiàn)在引用文件只需要js/xxx.js
就可以了
按需加載模塊
通過require.ensure
聲明的文件骨稿,會被按需加載,所以這些文件必須是一個獨立的個體姜钳,在需要被展示的時候才動態(tài)加載坦冠。一般路由組件的場景很多。
// 定義一個FirstPage的懶加載組件
let FirstPage = (location,cb) => {
require.ensure([],require => {
cb(null,require('../containner/xxx.js').default)//export default暴露的時候需要加一個default
},FirstPage)
}
// 在webpack的output中進(jìn)行相應(yīng)的配置
module.exports = {
output:{
path:__dirname + '/public/',
filename:'[name][hash].js',
chunkFilename:'[name].chunk.[hash].js',//單個文件名
sourceMapFilename: 'js/[name].js.map',//獨立文件sourcemap
}
}
注意:這里[name]會被塊名替換掉傲须,[hash]會被編譯的hash替換掉,其他同理趟脂。
Loaders
webpack中的核心應(yīng)該就是loaders了泰讽,通過不同的loader來打包處理不同的文件,比如說將es6昔期、es7轉(zhuǎn)換成瀏覽器識別的樣子已卸。
loader模塊需要單獨安裝,并且在modules
下進(jìn)行配置:
-
test
:匹配一個被loader處理的文件的拓展名的正則表達(dá)式 -
loader
:loader的名稱 -
include/exclude
:手動添加必須處理的文件(文件夾)或屏蔽不需要處理的文件(文件夾) -
query
:為loaders提供額外的設(shè)置選項()
module.exports = {
module:{
rules:[ // loaders數(shù)組硼一,里面放的都是loader
{
test:/\.json$/,
use:[{ //注意累澡,webpack1和webpack2的loader語法不太一樣
loader:"json-loader",
options:{xxx:"xxx",aaa:'aaa'}//向json-loader上配置參數(shù)。
//loader:"json?xxx=xxx&aaa=aaa" //還可以這樣配置參數(shù)
}]
}
]
}
}
Babel
babel是一個比較復(fù)雜的loader般贼,它可以編譯es6愧哟,es7,jsx哼蛆。
module.exports = {
module:{
rules:[
{
test:/\.js|jsx$/,
exclude:/node_modules/, //不處理node_modules這個文件夾,這里不需要引號
use:[{
loader:'babel-loader',
options:{presets:['es2015','react']}
}],
}
]
}
}
Babel配置選項
babel有自己的配置項蕊梧,一般都會把babel的配置項放在一個名為“.babelrc”的配置文件中.
{
"presets":["react","es2015"]
}
css
webpack提供兩個工具處理樣式表,css-loader
和style-loader
腮介,[css-loader][]可以讓我們使用@import
和url(...)
的方法實現(xiàn)require()
的功能肥矢,比如在react中,我們直接通過import 'xxx.css'
來引入css叠洗,style-loader
可以將所有的計算后的樣式加入頁面的內(nèi)聯(lián)樣式中甘改。
module.exports = {
module:{
rules:[
{
test:/\.css$/,
use:['style-loader','css-loader']
}
]
}
}
注意:style!css中旅东,加感嘆號的作用在于使同一文件能夠使用不同類型的loader
多個loader可以用在同一個文件上并且被鏈?zhǔn)秸{(diào)用,鏈?zhǔn)秸{(diào)用時從右到左執(zhí)行且loader之間用“十艾!”來分割抵代。
- webpack在入口文件內(nèi)搜索依賴項,發(fā)現(xiàn)有css依賴疟羹。
- css文件交給css-loader去處理
- css處理完之后主守,webpack將處理結(jié)果交給style-loader去處理
CSS module
可以讓css產(chǎn)生作用域的效果即scope
module.exports = {
module:{
rules:[
{
test:/\.css$/,
use:['style-loader','css-loader?module'] //在css加載器后面加了一個module
}
]
}
}
現(xiàn)在創(chuàng)建一個root.css文件
.root{background-color:red}
在jsx中引入
import React from 'react';
import './root.css';
export default class liberty extends React.Component{
render(){
return (
<div className = 'root'> // 添加類名
</div>
)
}
}
這個時候,其他組件如果也要使用root這個類名榄融,不會造成污染参淫。
自動添加css兼容性前綴
需要[postcss-loader][]和[autoprefixer][]插件
module.exports = {
module:{
rules:[
{
test:/\.css$/,
use:['style-loader','css-loader?module!postcss']
}
]
},
postcss:[
require('autoprefixer') //調(diào)用autoprefixer插件
]
}
常用命令
$ webpack --config webpack.min.js //另一份配置文件,作為生產(chǎn)和開發(fā)環(huán)境的區(qū)分
$ webpack --display-error-details //顯示異常信息
$ webpack --watch //監(jiān)聽變動并自動打包
$ webpack -p //壓縮混淆腳本,這個非常非常重要愧杯!
$ webpack -d //生成map映射文件涎才,告知哪些模塊被最終打包到哪里了
常用插件
ExtractTextPlugin:可以從bundle中提取出特定的內(nèi)容到一個文件中,可以抽離公共樣式
let ExtractTextPlugin = require("extract-text-webpack-plugin");
let extractCSS = new ExtractTextPlugin('stylesheets/[name].css');
module.exports = {
module:{
rules:[
{
test:/\.css/,
use:extractCSS.extract(['css','sass'])
}
]
}
plugins:[
extractCSS
]
}
CommonsChunkPlugin:可以將多個入口中的公共內(nèi)容提取出來。
CommonsChunk:可以用來解決多個js引用了同一個文件導(dǎo)致該文件多次請求的情況力九,它會把這個文件打包進(jìn)一個公共的文件內(nèi)耍铜,被瀏覽器緩存。
module.exports = {
plugins:[
new webpack.optimize.CommonsChunkPlugin({
name:"commons",
filename:"commons.js",
minChunks:2 //加載次數(shù)
})
]
}
現(xiàn)在的如果有任意模塊被加載了兩次或更多跌前,它就會被打包進(jìn)一個叫commons.js
的文件里棕兼。