使用webpack構(gòu)建應(yīng)用的方法步驟
如何使用webpack
npm init -y npm install webapck webpack-cli --save-dev touch webpack.config.js
在webpack.config.js中下面添加內(nèi)容
const path = require('path'); module.exports = { entry: './src/index.js', output: { filename: 'main.js', path: path.resolve(__dirname, 'dist') } };
- entry:工程資源的入口,可以是單個文件,也可以是多個文件,通過每一個資源入口,webpack會一次去尋找它的依賴進行模塊打包。我們可以把entry理解為整個依賴樹的根,每個入口都將對應(yīng)一個最終生成的打包結(jié)果。
- output:這是一個配置對象,通過它我們可以對最終打包的產(chǎn)物進行配置,這里配置了兩個屬性,:
- path:打包資源放置的路勁,必須為絕對路徑。
- filename:打包結(jié)果的文件名。
定義好配置文件后,用npx webpack或者./node_modules/.bin/webpack執(zhí)行
使用loader
項目中需要引入一個css文件,如果直接用webpack去執(zhí)行就會報錯,需要再webpack中加入loader機制
module.exports = { ... module: { rules: [ { // 用正則去匹配 .css 結(jié)尾的文件,然后需要使用 loader 進行轉(zhuǎn)換 test: /\.css$/, use: ['style-loader', 'css-loader'] } ] } }
編譯之前還需要安裝style-loader和css-loader
npm install --save-dev style-loader css-laoder
注意:
use屬性的值是一個使用loader名稱組成的數(shù)組,loader執(zhí)行的順序是從后往前的,由于loader執(zhí)行有順序,故不能寫成這樣
use: ['css-loader', 'style-loader']
每個loader都可以通過URL queryString的方式傳入?yún)?shù),比如'css-loader?url'
style-loader的原理:是將css的內(nèi)容使用javascript的字符串存儲起來,在網(wǎng)頁執(zhí)行javascript時通過DOM操作,動態(tài)地向HTML head標(biāo)簽里插入HTML style標(biāo)簽。
配置loader的方式也可以用Object來實現(xiàn)
use: ['style-loader', { loader: 'css-loader', options: { url: true } }]
使用plugin
loader的作用是被用于轉(zhuǎn)換某些類型的模塊,而插件則可以用于執(zhí)行范圍更廣的任務(wù),插件的范圍包括,從打包優(yōu)化和壓縮,一直到重新定義環(huán)節(jié)中的變量。
如果想要使用一個插件,我們只需要require()它,然后把它添加到plugins數(shù)組中。我們可以在一個配置文件中因為不同的目的多次使用用一個插件,因此我們可以使用new操作符來創(chuàng)建它的實列。
上面使用loader把css加載到j(luò)s中去,現(xiàn)在使用extract-text-webpack-plugin插件把bundle.js文件里的css提取到單獨的文件中
// 提取 css 的插件 const ExtractTextPlugin = require('extract-text-webpack-plugin') module: { rules: [ { // 用正則去匹配 .css 結(jié)尾的文件,然后需要使用 loader 進行轉(zhuǎn)換 test: /\.css$/, loaders: ExtractTextPlugin.extract({ //轉(zhuǎn)換 .css需要使用的 loader use: ['css-loader'] }) } ] }, plugins: [ //從 js 文件中提取出來的 .css 文件名稱 new ExtractTextPlugin({ filename: 'main.css' }) ]
編譯之前需要安裝extract-text-webpack-plugin
npm install --save-dev extract-text-webpack-plugin
執(zhí)行webpack時報錯需要這樣安裝
npm install extract-text-webpack-plugin@next
DevServer
安裝
npm install webpack-dev-server --save-dev
然后進行簡單的配置
devServer:{ port: 3000, publicPath: "/dist" }
然后用./node_modules/.bin/webpack-dev-server
執(zhí)行
資源壓縮
npm i uglifyJSPlugin-webpack-plugin --save-dev
配置文件
const UglifyJSPlugin = require('uglifyjs-webpack-plugin') plugins: [ new UglifyJSPlugin({ //默認(rèn)是 false 需要手動開啟 parallel: true }) ]
或者
optimization: { minimizer: [new UglifyJsPlugin()], },
按需加載
在代碼層面,webpack支持兩種方式進行異步模塊加載,一種是CommonJS形式的require.ensure,一種是ES6 Module形式的異步import()
異步加載的腳本不允許使用document.write,所以將module.js的代碼改成console.log
export const log = function(){ console.log('module.js loaded.') }
編輯app.js,將module.js以異步的形式加載進來
import('./module.js').then(module =>{ module.log() }).catch(error => "An error occurred while loading the module") document.write('app.js loaded.')
修改配置
module.exports = { mode: "production", entry: './app.js', output: { filename: 'main.js', path: path.resolve(__dirname, 'dist'), publicPath: "./dist" }, }
這里我們在output中添加了一個配置項publicPath,它是webpack中一個很重要有很容易引起迷惑的配置,當(dāng)我們的工程中有按需加載以及圖片和文件等外部資源時,就需要它來配置這些資源的路徑,否則頁面上就會報404,這里我們將publicPath配置為相對于html的路徑,使按需加載的資源生產(chǎn)在dist目錄下,并且能正確地引用到它。
重新打包之后你會發(fā)現(xiàn)打包結(jié)果中多出一個1.mian.js,這里面就是將來會被異步加載進來的內(nèi)容。刷新頁面并查看chrome的network標(biāo)簽,可以看到頁面會請求1.main.js。它并不來源于index.html中的引用,而是通過main.js在頁面插入了script標(biāo)簽來將其引入的。
使用webpack的構(gòu)建特性
從2.0.0版本開始,webpack開始加入了更多的可以優(yōu)化構(gòu)建過程的特性。
tree-shaking
在關(guān)于模塊的那一篇文章中我們提到過,ES6 Module的模塊依賴解析是在代碼靜態(tài)分析過程中進行的。換句話說,它可以在代碼的編譯過程中得到依賴樹,而非運行時。利用這一點webpack提供tree-shaking功能,它可以幫助我們檢測工程中哪些模塊有從未被引用到的代碼,這些代碼不可能被執(zhí)行到,因此也稱為“死代碼”。通過tree-shaking,webpack可以在打包過程中去掉這些死代碼來減小最終的資源體積。
開啟tree-shaking特性很簡單,只要保證模塊遵循ES6 Module的形式定義即可,這意味著之前所有我們的例子其實都是默認(rèn)已經(jīng)開啟了的。但是要注意如果在配置中使用了babel-preset-es2015或者babel-preset-env,則需要將其模塊依賴解析的特性關(guān)掉,如:
presets: [ [env, {module: false}] ]
這里我們測試一下tree-shaking的功能,編輯module.js:
// module.js export const log = function() { console.log('module.js loaded.'); } export const unusedFunc = function() { console.log('not used'); }
打開頁面查看1.main.js的內(nèi)容,應(yīng)該可以發(fā)現(xiàn)unusedFunc的代碼是不存在的,因為它沒有被別的模塊使用,屬于死代碼,在tree-shaking的過程中被優(yōu)化掉了。
tree-shaking最終的效果依賴于實際工程的代碼本身,在我對于實際工程的測試中,一般可以將最終的體積減小3%~5%??傮w來看,我認(rèn)為如果要使tree-shaking發(fā)揮真正的效果還要等幾年的時間,因為現(xiàn)在大多數(shù)的npm模塊還是在使用CommonJS,因此享受不了這個特性帶來的優(yōu)勢。
scope-hoisting
scope-hoisting(作用域提升)是由webpack3提供的特性。在大型的工程中模塊引用的層級往往較深,這會產(chǎn)生比較長的引用鏈。scope-hoisting可以將這種縱深的引用鏈拍平,使得模塊本身和其引用的其它模塊作用域處于同級。這樣的話可以去掉一部分 webpack的附加代碼,減小資源體積,同時可以提升代碼的執(zhí)行效率。
目前如果要開啟scope-hoisting,需要引入它的一個內(nèi)部插件:
module.exports = { plugins: [ new webpack.optimize.ModuleConcatenationPlugin() ] }
scope-hoisting生效后會在bundle.js中看到類似下面的內(nèi)容,你會發(fā)現(xiàn)log 的定義和調(diào)用是在同一個作用域下了:
// CONCATENATED MODULE: ./module.js const log = function() { console.log('module.js loaded.'); } // CONCATENATED MODULE: ./app.js log();
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
JS旋轉(zhuǎn)實現(xiàn)轉(zhuǎn)盤抽獎效果
這篇文章主要為大家詳細介紹了JS旋轉(zhuǎn)實現(xiàn)轉(zhuǎn)盤抽獎效果,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-02-02TypeScript調(diào)整數(shù)組元素順序算法
數(shù)組類型在TS中可以使用多種方式,比較靈活,下面這篇文章主要給大家介紹了關(guān)于TypeScript調(diào)整數(shù)組元素順序算法的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下2022-04-04JavaScript中三種非破壞性處理數(shù)組的方法比較
在這篇文章中,我們將會探索處理數(shù)組的三種方法:for…of循環(huán)、數(shù)組方法.reduce()和數(shù)組方法.flatMap(),文中的示例代碼講解詳細,感興趣的可以了解一下2023-06-06