一、webpack和npm的關系
- npm是包管理器,及可以執(zhí)行命令包(webpack可以看成是功能強大的命令包,除了webpack還有其它如webpack-dev-server);
- webpack可以看成是功能強大的命令包:它還可以執(zhí)行其它的功能包(裝載機,插件)
二、全局安裝/項目安裝?[1]
重點就在
這個包是否要作為CMD命令來使用及本地項目是否都差不多,因此放在全局
- 這個包要作為CMD命令使用:要全局安裝 。如yarn cnpm webpack-dev-server等
即安裝到node_global,因為node_global在系統(tǒng)環(huán)境中配置了路徑,
故而里面的腳本能在cmd中直接運行
此時這個命令的運行環(huán)境是全局環(huán)境:對應全局的webpack版本
- 不作為CMD命令使用:項目安裝
在package.json的scripts中也可以執(zhí)行命令包,此時通過npm run 命令別名來執(zhí)行
因為Npm會臨時把本地項目命令加載到系統(tǒng)環(huán)境path中,故而命令包放在本地也能通過npm run來執(zhí)行√
如果本地有安裝,則執(zhí)行本地的。否則執(zhí)行的是全局的命令包。對應的執(zhí)行環(huán)境webpack也是一樣的。
三、打包前的準備工作(操作的webpack為3.8.1)
- 創(chuàng)建項目:
$ npm init- 全局安裝webpack:
$ npm install webpack -g及腳手架$ npm install webpack-cli -g全局安裝是為了CMD使用
webpack 命令
- 本地安裝webpack:
$ npm install webpack --save-dev
四、js的打包
方式①:
$ webpack 源文件 目標文件即:把源文件js打包到目標文件
如:$ webpack ./src/app.js ./dist/main.js其它參數(shù):
--watch開啟熱跟新-p壓縮目標文件-d調試時,方便定位源文件問題:
- 命令行太長,寫法比較復雜
- 直接采用的是webpack命令,此時,運行環(huán)境為 全局的webpack包,并非項目的webpack版本,可能會產(chǎn)生和項目的一些沖突
方式②:
通過配置文件,來簡化webpack命令創(chuàng)建配置文件 webpack.config.js module.exports={ entry:'./src/app.js', output:{ path: __dirname + '/dist', //__dirname 是Node的變量,表示根目錄。注意:path只能是絕對路徑 filename: 'main.[hash:5].js' //[hash:5]表示取hash的5位,這邊是為了更新瀏覽器本地緩存 } //json文件不能注釋,這邊是為了解釋說明用的因為webpack會自動會查找webpack.config.js,且這邊已經(jīng)配置好了源文件及目標文件
此時可以:$ webpack即可打包。或$ webpack --watch等問題:
- 命令行還是不夠簡潔,一些參數(shù)還是沒辦法配置
- (同上)直接采用的是webpack命令,此時,運行環(huán)境為 全局的webpack包,并非項目的webpack版本
方式③:
通過package.json的scripts來運行腳本修改package.json的scripts: "scripts": { "build": "webpack --watch -d", "prod": "webpack -p" }此時,可以直接
$ npm run build或$ npm run prod來運行腳本優(yōu)點:
命令全都由npm來運行,且命令簡潔明了(便于知道有哪些命令)npm來運行,所以采用的是項目的腳本(包括其它的腳本也是一樣)
五、結合html
前面已經(jīng)學會js的打包,但畢竟運行在瀏覽器的入口是html,那怎么和html結合呢?
方式①:
創(chuàng)建html,手動引入打包后的js。問題:
- 打包后的style,script標簽要手動寫入html。麻煩
- 以及hash問題,每次生成的打包文件名還不一樣,又要重新寫入html。麻煩
方式②:使用
html-webpack-plugin插件作用:
- 程序還是正常從entey入口開始打包
然后,對html模板,引入<script src="打包后的js">,及其它操作(壓縮,hash等等)安裝插件 $ npm install html-webpack-plugin --save-dev
使用插件(在webpack.config.js中引入及掛載) 引入: const HtmlWebpackPlugin = require('html-webpack-plugin'); 掛載: module.exports={ plugins: [ new HtmlWebpackPlugin({ template:"./src/index.html", //html的模版文件 filename: 'one.html', //生成目標html的名字 minify: {collapseWhitespace:true} ,//壓縮html及配置壓縮類型 hash:true//會在所有注入的靜態(tài)資源添加webpack每次編譯產(chǎn)生的唯一hash值 }) ] } //hash:true的效果 <script type="text/javascript" src="main.dce13.js?dce1306176497ad4a85d"></script></body> 可以發(fā)現(xiàn)dce13:為main.[hash:5]生成的hash值 ?dce1306176497ad4a85d為這次生成的hash值,所有靜態(tài)文件都添加了這個html-webpack-plugin詳細配置點擊查看
minify的詳細配置點擊查看
高級篇----多html的配置
- 從實際意義出發(fā),肯定需要配置多入口
之前entry是string類型,這次我們采用array類型 entry: { "entry1":'./src/app.js', //其中,"entry1"作為chunk代碼塊 "entry2":'./src/app1.js', "entry3":'./src/app2.js', },
使用插件 plugins: [ //tips: plugins執(zhí)行順序也是從后到前執(zhí)行。即先執(zhí)行底下的插件,再上面的插件 new HtmlWebpackPlugin({ template:"./src/index_other.html", filename: 'two.html', //這個是第二個html的出口 minify: {collapseWhitespace:true} , hash:true, chunks:['entry2','entry3'] //這邊測試處理兩個,也可以通過excludeChunk:['entry1'] 取余 }), new HtmlWebpackPlugin({ template:"./src/index.html", filename: 'one.html', minify: {collapseWhitespace:true} , hash:true, chunks:['entry1'] //這個配置是要處理的chunk代碼塊,默認為all即所有入口的都處理 }) ] -------------------------------------------------------- 說明: chunks:[] //數(shù)組內的值為entry配置里面的key值。這邊即'entry1','entry2','entry3' excludeChunk:[]//這個配置是除了數(shù)組內的chunk代碼塊會去處理。即取反
這邊還有個問題:多個html-webpack-plugin插件處理入口,于是會生成多個目標js。 之前: output:{ path: __dirname + '/dist', filename: 'main.[hash:5].js' //多html-webpack-plugin插件時,會生成多個同名的該文件,會同名覆蓋 } 改為=> output:{ path: __dirname + '/dist', filename: '[name].[hash:5].js' //name為對應entry的chunk名,同上 } 說明:[name]表示為對應entry的chunk名,同上
總結:對比一個html,區(qū)別在于:
需要多個入口,然后使用多個html-webpack-plugin插件處理入口對應的chunk,然后生成多html
六、結合css
前面學習了js的打包,以及把打包后的Js結合html,結合html我們采用插件來自動化幫我們處理一些事情。
但是怎么結合css呢,css不是瀏覽器入口,只能通過源js引入該css。再處理
但是webpack默認只認得js,因此要采用裝載機來處理css,再放到html中。
方式①:使用
'style-loader', 'css-loader'。這種是<style>樣式的方式原理:
- 在js中引入該css。import css from './one.css';
- 然后,
css-loader,實現(xiàn)從對應css文件導入文件到js中- 然后,
style-loader,實現(xiàn)從js中,提取出css,然后在html中,寫入<style>中安裝裝載機 $ npm install css-loader style-loader --save-dev
使用裝載機(在webpack.config.js中掛載) 相比插件不用引進 module: { rules: [ { test: /\.css$/, //正則表達式,匹配對應的后綴文件,然后用底下對應的裝載機處理 use: [ 'style-loader', 'css-loader' ] //裝載順序為***從右到左*** } ] }說明:
css-loader:即:編譯。加載.css文件,注入到js文件中,以字符串的形式存在style-loader:即:提取。使用<style>將css-loader內部樣式注入到我們的HTML頁面- css-loader/style-loader詳細配置點擊查看
這種方式在html生成的是<style>標簽
方式②:結合
extract-text-webpack-plugin插件:實現(xiàn)css分離成文件。這種是<link>樣式的方式安裝插件 $ npm install extract-text-webpack-plugin --save-dev
使用插件 引入: const ExtractTextPlugin = require('extract-text-webpack-plugin'); //這邊對比css-loader/style-loader的區(qū)別 module: { rules: [ { test: /\.css$/, use:ExtractTextPlugin.extract({ fallback: 'style-loader', //提取要用到的裝載機 use: [ 'css-loader' ] //編譯要用到的裝載機 }) } ] } 以及配置plugins: plugins{ new ExtractTextPlugin('style.css') //生成目標css的文件名為style.css }說明:
- 通過
extract-text-webpack-plugin插件實現(xiàn)了css的分離,而不是注入js中- extract-text-webpack-plugin詳細配置點擊查看
- 和webpack4.0+ 不兼容
這種方式在html生成的是<link>標簽- 所以和第一種方式的優(yōu)劣勢對比即為:
<style>和<link>樣式的優(yōu)劣勢對比及css有獨立hash等
這邊補充對于scss的css文件的處理
安裝scss裝載機: $ npm install sass-loader node-sass --save-dev
方式一下使用sass-loader裝載機: module: { rules: [ { test: /\.scss$/, //這邊匹配文件后綴為.scss use: [ 'style-loader', 'css-loader' ,"sass-loader"] //只是這邊后面增加該裝載機 } ] } ------------------------------------------------------------------ 方式二下使用sass-loader裝載機: module: { rules: [ { test: /\.scss$/, use:ExtractTextPlugin.extract({ fallback: 'style-loader', use: [ 'css-loader',"sass-loader" ] }) } ] } 以及配置plugins: plugins{ new ExtractTextPlugin('style.css') }其它補充
添加hash:plugins: [new ExtractTextPlugin('style.[hash:5].css')]
七、webpack-dev-server插件的使用
前面有介紹CMD命令包對于全局安裝或本地安裝的選擇,點擊回顧
方式①:全局安裝$ npm install webpack-dev-server -g
此時,在CMD即可使用該命令:$ webpack-dev-server//注意此時運行環(huán)境為全局的Webpack版本
方式②:項目安裝
$ npm install webpack-dev-server --save-dev
此時可以通過配置scripts可以讓npm來運行腳本"scripts": { "dev": "webpack-dev-server" }此時,可以直接
npm run dev來開啟本地服務
補充
webpack.config.js中配置 devServer: { port: 9000, //這邊配置端口號 open:true //這邊會自動打開瀏覽器 },說明
- 配置webpack-dev-server 運行時報錯配置 Can't resolve 'webpack/hot/dev-server' 。
說明項目中,沒有安裝webpack- webpack-dev-server生成的包并沒有放在你的真實目錄中,而是放在了內存中
- 和webpack4.0+不兼容,
這邊webpack@3.8.1安裝2.9.1- webpack-dev-server的詳細配置點擊查看
- 對比
webpack --watch避免了打包文件及實現(xiàn)了熱更新
八、
九、區(qū)分生產(chǎn)環(huán)境和開發(fā)環(huán)境
- 配置部分區(qū)分
- 方式①:在webpack.json的scripts運行腳本時,增加變量并賦值
eg:
"prod": " SET NODE_ENV=production & SET hcl=huchunlin && webpack -p",
配置部分使用:console.log(process.env.NODE_ENV);console.log(process.env.hcl);
說明:process.env.變量來訪問
window系統(tǒng)需要SET 。max系統(tǒng)不需要
- 方式②:不同命令進入,即會執(zhí)行不同的配置文件
eg:
"prod": " webpack -p --config ./config/prod.js",
即通過--config來執(zhí)行指定配置文件
- 方式③:相結合
- 源代碼(打包后的文件)區(qū)分
通過webpack.DefinePlugin來定義源代碼的全局變量。在編譯時會進行替換webpack.config.js中=>定義全局變量 ----------------------------------------------------------------- plugins: [ new webpack.DefinePlugin({ "hcl": JSON.stringify('這個是在webpack.config定義的變量') }) ]
源代碼中,比如在app.js中=>使用全局變量 ----------------------------------------------------------------- console.log(hcl)
- 配置文件和源代碼都要能區(qū)分:結合①和②
-
二、全局安裝/項目安裝 ?