入口,Webpack執行構建的第一步將從Entry開始,可抽象成輸入。css
module.exports = {
entry: './path/to/my/entry/file.js'
}
複製代碼
module.exports = {
entry: {
one: './path/one.js',
two: './path/two.js'
},
plugins:[
new HtmlWebpackPlugin({
title:'第一個頁面',
template: './pages/one.html', // 指定第一個頁面的模板
filename: './pages/one.html', // 指定第一個頁面打包完成後的文件名
chunks: ['one','two'] // 指定第一個頁面要打包進入的js
}),
new HtmlWebpackPlugin({
title:'第二個頁面',
template: './pages/two.html', // 指定第二個頁面的模板
filename: './pages/two.html', // 指定第二個頁面打包完成後的文件名
chunks: ['one','two'] // 指定第二個頁面要打包進入的js
}),
]
}
複製代碼
網上關於單頁面和多頁面的優勢和缺點都有比較詳細的描述,具體須要應用單頁面仍是多頁面得根據項目的需求來選擇。html
通常單頁面的配置都有相應的腳手架,好比vue-cli,集成了wp,減小了配置webpack的不少繁瑣的工做vue
多頁面應用如今沒有腳手架,能夠進行配置,具體的實例可參考這篇:node
多頁面想向單頁面實現組件共用和封裝,能夠參考這篇進行配置,須要引入ejs模板,參考這篇:jquery
juejin.im/post/5a35f6…webpack
模塊,在Webpack裏一切皆模塊,一個模塊對應一個文件。Webpack會從配置的Entry開始遞歸找出全部依賴的模塊。 ####配置Loaderweb
test:匹配要進行轉換的文件,使用正則表達式來匹配。正則表達式
include: 只包含指定目錄的文件進行轉換,加快webpack的編譯速度。vue-cli
exclude: 排除某個文件的轉換,加快編譯和搜索速度。
use:對use後面加參數,好比進行緩存和壓縮,也能夠加快編譯的速度。
module:{
rules: [
{
//解析js文件
test: /\.js$/,
// 用babel-loader轉換js文件
// ?cacheDirectory表示傳給babel-loader的參數,用於緩存babel的編譯結果,加快從新編譯的速度
use: ['babel-loader?cacheDirectory']
// 只命中src目錄裏的Js文件,加快webpack的編譯速度
include: path.resolve(_dirname,'src')
},
{
//解析Scss文件
test: /\.scss$/,
// 使用一組loader去處理scss文件
// 處理順序爲從後到前,即先交給scss-loader處理,再將結果交給css-loader,最後交給style-loader
use: ['style-loader','css-loader','sass-loader'],
// 排除node_modules目錄下的文件
exclude: path.resolve(__dirname,'node_modules')
},
{
// 對非文本文件採用file-loader加載
test: /\.(gif|png|jpe?g|eot|woff|ttf|svg|pdf)$/,
use: ['file-loader']
}
]
}
複製代碼
{
test:[
/\.jsx?$/,
/\.tsx?$/
],
include:[
path.resolve(__dirname,'src'),
path.resolve(__dirname,'tests')
],
exclude:[
path.resolve(__dirname, 'node_modiles'),
path.resolve(__dirname, 'bower_modules')
]
}
複製代碼
noPaese配置項可讓Webpack忽略對部分沒采用模塊化的文件的遞歸解析和處理,這樣作的好處是能提升構建性能。 緣由是一些庫如jQuery,ChartJS龐大又沒有采用模塊化的標準,讓Webpack去解析這些文件既耗時又沒有意義。
noParse: /jquery|chartjs/
複製代碼
noParse: (content) => {
//content表明一個模塊的文件路徑
//返回true或false
return /jquery|chartjs/.test(content)
}
複製代碼
由於Webpack是以模塊化的js文件爲入口的,因此內置了對模塊化js的解析功能,支持AMD,CommonJS,SystemJS,ES6 parse屬性能夠更細粒度地配置哪些模塊語法被解析,哪些不被解析。
同noParse配置項的區別在於.parser能夠精確到語法層面,而noParse只能控制哪些文件不被解析。
parse的使用方法以下:
modele:{
rules:[
test: /\.js$/,
use: ['babel-loader'],
parser: {
amd: false, //禁用AMD
commonjs: false, // 禁用CommonJS
system: false, // 禁用 SystemJS
harmony: false, // 禁用ES6 import/export
requireInclude: false, // 禁用requireInclude
requireEnsure: false, // 禁用requireEnsure
requireContext: false, // 禁用requireContext
browserify: false, // 禁用browserify
requireJs: false // 禁用requirejs
}
]
}
複製代碼
模塊轉換器,用於將模塊的原內容按照需求轉換成新內容。
Loader的執行順序是由後到前的。
每Loader均可以經過URL querystring的方式傳入參數,例如 css-loader?minimize中的minimize告訴css-loader要開啓css壓縮。
向loader中傳入屬性的方式除了能夠經過querystring實現,還能夠經過object實現。
user:[
'style-loader',{
loader:'css-loader',
options:{
minimize:true
}
}
]
複製代碼
use:[
{
loader:'babel-loader',
options:{
cacheDirectory:true
},
// enforce: 'post'的含義是將該loader的執行順序放到最後
// enforce: 'pre'的含義是將loader的執行順序放到最前面
}
]
複製代碼
拓展插件,在Webpack構建流程中的特定時機注入拓展邏輯。
Plugin的配置很簡單,plugins的配置項接受一個數組,數組裏的每一項都是一個要使用的Plugin的實例,Plugin須要的參數經過構造函數傳入。
const CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin')
module.exports = {
plugins: [
// 全部頁面都會用到的公共代碼被提取到common代碼塊中
new CommonsChunkPlugin({
name: 'common',
chunks: ['a','b']
})
]
}
複製代碼
const ExtractTextPluginn = require('extract-text-webpack-plugin')
module:{
reules:[
{
textL /\.css$/,
loaders: ExtractTextPlugin.extract({
use:[
'css-loader'
]
}),
}
]
},
plugins: [
new ExtractTextPlugin({
//從.js文件中提取出來的.css文件的名稱
filename: `[name]_[contenthash:8].css`
})
]
複製代碼
webpack在啓動後會從配置的入口模塊出發找出全部依賴的模塊,resolve配置webpack如何查找模塊所對應的文件
resolve.alias配置項經過別名來將原導入路徑映射成一個新的導入路徑。例如使用一下配置:
resolve:{
alias:{
components: './src/components'
}
}
複製代碼
當經過**import Button from 'components/button'**導入時
實際上被alias等價替換成了import Button from './src/components/button'
在導入語句沒帶文件後綴時,Webpack會自動帶上後綴後去嘗試訪問文件是否存在。
resolve.extensions用於配置在嘗試過程當中用到的後綴列表,默認是:
extensionsL ['.js','.json']
複製代碼
也就是說,當遇到require('./data')這樣的導入語句時,Webpack會先尋找./data.js文件,若是該文件不存在,就去找./data.json文件,若是仍是找不到就報錯。
若是resolve.enforceExtension被配置爲true,則全部導入語句都必須帶文件後綴,例如開啓前import './foo'能正常工做,開啓後就必須寫成**import './foo.js' **
devltool配置Webpack如何生成source map,默認值是false,即不生成source map,若想構建出的代碼生成source map以方便調試,則能夠這樣配置:
module.export = {
devtool: 'source-map'
}
複製代碼
開啓source-map會方便咱們開發中的調試,方便咱們定位到具體的代碼問題,當也會影響一下相關的構建性能問題,全部要作出多配置文件,開發環境配置和生產環境配置
source-map模式下會輸出質量最高且最詳細的Source Map,這會形成構建速度緩慢,特別是在開發過程當中須要頻繁修改時會增長等待時間
在Source-Map模式下會將Source Map暴露,若構建發佈到線上的代碼的source map暴力,就等同於源碼被泄露
爲了解決以上兩個問題,能夠這樣作,以下所述
在開發環境下devtool設置成cheap-module-eval-source-map,由於生成這種source map的速度最快,能加速構建。因爲在開發環境下不會作代碼壓縮,因此在source map的即便沒有列信息,也不會影響斷電調試.
在生產環境下將devtool設置成hidden-source-map,意思是生成最詳細的source map,但不會將source map暴露出去。因爲生產環境下會作代碼壓縮,一個js文件只有一行,因此須要列信息。
在生產環境下一般不會將Source Map上傳到http服務器讓用戶獲取,而是上傳到JavaScript錯誤收集系統,在錯誤收集系統上根據Source Map和收集到的JavaScript運行錯誤隊棧,計算出錯誤所在源碼的位置。
不要在生產環境下使用inline模式的Source Map,由於這會使JavaSctipt文件變的很大,並且會泄露源碼。
External用來告訴Webpack要構建的代碼中使用了哪些不用被打包的模塊,也就是說這些模板是外部環境提供的,Webpack在打包時能夠忽略它們
經過externals能夠告訴Webpack在js運行環境中已經內置了哪些全局變量,不用將這些全局變量打包到代碼中而是直接使用它們。
moudle.export = {
externals: {
//將導入語句裏的jquery替換成運行環境裏的全局變量jQuery
jquery: 'jQuery'
}
}
複製代碼
優化開發體驗
優化開發體驗的目的是提高開發效率,減小每次構建的耗時
1. 優化構建速度
2. 優化使用體驗,經過自動化手段完成一些重複的工資哦,讓咱們專一於解決問題自己。
複製代碼
優化輸出質量
呈現用戶體驗更好的網頁,減小首屏加載時間,提高性能流暢度。
1. 縮小文件的搜索範圍
2. 優化Loader的配置,經過include去命中 只有哪些文件去處理,經過exclude去去除哪些文件不須要處理,好比node_module
3. 優化resolve.modules配置
resolve.modules用於配置Webpack去哪些目錄下尋找第三方模塊。
resolve.modelus的默認值是['node_modules']含義是先去當前目錄的./node_modules目錄下去找咱們想找的模塊,若是沒找到,就去上一級目錄../node_modules中找,再沒有就去../../node_modules中找,以此類推
當安裝的第三方模塊都放在項目根目錄的./node_modules目錄下時,就沒有必要按照默認的方式去一層層的尋找,能夠指明存放第三方模塊的絕對路徑,以減小尋找,配置以下:
module.exports = {
resolve: {
// 使用絕對路徑指明第三方模塊存放的位置,以減小搜索步驟
// 其中,__dirname表示當前工做目錄,也就是項目根目錄
modules: [path.resolve(__dirname,'node_modules')]
}
}
4.優化resolve.alias配置,跳過遞歸解析操做
5.優化resolve.extensions配置減小後綴,後綴要儘量少,提高速度
6.優化noParse配置
複製代碼
包含大量複用模塊的動態連接庫只需被編譯一次,在以後的構建過程當中被動態連接庫包含的模塊將不會被從新編譯,而是直接使用動態連接庫中的代碼。因爲動態連接庫中大多數包含的是經常使用的第三方模塊,例如react,react-dom,因此只要不升級這些模塊的版本,動態連接庫就不用從新編譯。
Webpack已經內置了對動態連接庫的支持,須要經過如下兩個內置的額插件接入。
運行在Node.js之上的Webpack是單線程模型,Happy Pack將任務分解給多個子進程去併發執行,子進程處理完後再講結果發送給主進程,因爲js是單線程模型,因此想要發揮多核cpu的功能,就只能經過多進程實現,而沒法經過多線程實現。
整個Webpack構建流程中,最耗時的流程可能就是loader對文件的轉換操做了,由於要轉換的文件數據量巨大,並且這些轉換操做都只能一個一個地處理。HappyPack的核心原理就是將這部分任務分解到多個進程中去並行處理,從而減小總的構事件。
本來會使用Uglifyjs去一個一個壓縮再輸出
Paralleuglifyplugin會開啓多個子線程,將對多個文件的壓縮工做分配給多個子進程完成,每一個子進程其實仍是經過uglify去壓縮代碼,可是變成了並行執行,因此Paralleuglifyplugin能更快地完成對多個文件的壓縮工做
文件監聽是發現源碼發生變化時,自動從新構建出新的輸出文件.
讓Webpack開啓監聽模式,有以下兩種方式。
忽略node_modules
module.export = {
watchOptions:{
ignored: /node_modules/
}
}
複製代碼
##區分環境 區分開發環境和生產環境,指定對用的不一樣調試模式Source Map,是否開啓壓縮,是否提取公共代碼等
相同的資源被重複加載,浪費用戶的流量和服務器成本
頁面須要加載的資源太大,會致使網頁首屏加載緩慢,影響用戶體驗。
webpackchunkplugin
複製代碼
如何按需加載
在爲單頁應用作按需加載優化時,通常採用如下原則
將整個網站劃分紅一個個小功能,再按照每一個功能的相關程度將它們分紅幾類
將每一類合併爲一個chunk,按需加載對應的chunk.
不要按需加載用戶首次打開網站是須要看到的畫面所對應的功能,將其放到執行入口所在的Chunk中,以減小用戶能感知的網頁加載時間。