一.爲何要學習webpackcss
如今的前端網頁功能豐富,特別是SPA(single page web application 單頁應用)技術流行後,JavaScript的複雜度增長和須要一大堆依賴包,還須要解決SCSS,Less……新增樣式的擴展寫法的編譯工做。因此現代化的前端已經徹底依賴於WebPack的輔助了。html
如今最流行的三個前端框架,能夠說和webpack已經緊密相連前端
React.js+WebPackvue
Vue.js+WebPacknode
AngluarJS+WebPackreact
能夠看出,不管前端走哪條線,都要有很強的Webpack知識jquery
二. webpack是什麼webpack
其實說白了,webpack就是模塊打包機。es6
在webpack看來,一切皆模塊。Webpack所作的事情就是:分析項目結構,找到js模塊以及其餘一些瀏覽器不能直接運行的語言,sass typeScript等,將其轉換打包成合適的格式。共瀏覽器使用。在3.0之後,webpack還有了優化項目的功能web
第一點:打包,webpack多個js文件打包成一個文件。減小服務器壓力和下載帶寬。減小請求次數和壓縮js css img(對原始圖片進行壓縮處理、調整圖片的分辨率和尺寸;服務器開啓Gzip壓縮功能壓縮頁面文本)
第二點:轉換,可以把less,scss等擴展性語言,以及各類類型的js文件都轉換成標準的能被瀏覽器識別的語言
第三點:優化。Webpack3.0之後,擔任着優化和提高性能的責任(好比第三方類庫的分離,提取公共代碼等)
總結起來,就是打包/轉換/優化。話很少說,咱們一塊兒來看下怎麼使用webpack。若是有不當的地方,歡迎你們糾正,一塊兒學習。
三. webpack基礎應用
1.安裝
webpack安裝的兩種方式
1. 全局安裝:npm install -g webpack
2.本地安裝: npm install --save-dev webpack(@version)
webpack 版本查看 :webpack -v
全局安裝就是安裝到全局目錄下(經過 npm config set prefix 「目錄路徑」 來設置。經過 npm config get prefix 來獲取當前設置的目錄)
可是對於大多數項目咱們推薦安裝到本地,緣由是可防止不一樣項目依賴不一樣版本的 Webpack 而致使衝突。
安裝好以後,咱們就能夠在項目進行webpack的配置了
2. webpack基本配置-webpack.config.js
module.exports={
entry:{}, // 入口文件的配置項
output:{}, // 出口文件的配置項
module:{}, // 模塊:例如解讀CSS,圖片如何轉換,壓縮
plugins:[], // 插件,用於生產模版和各項功能
devServer:{} // 配置webpack開發服務功能
}
單入口:
module.exports={
entry:{
entry1: './src/entry.js’
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: ‘bundle.js'
}
}
多入口:
output.path對應一個絕對路徑,path.resolve主要是用於設置絕對路徑,而且輸出文件夾建議是要使用絕對路徑的.
module.exports={
entry1:{
entry1: './src/entry.js',
entry2: './src/entry.js’
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: ‘[name].js’
},
……
}
3. 所見即所得之熱更新-- devServer
devServer: {
//設置基本目錄結構,使用絕對目錄
contentBase:path.resolve(__dirname,‘dist’),
//服務器的IP地址,可使用IP也可使用localhost
host:‘localhost’,
//服務端壓縮是否開啓(自行學習)
compress:true,
//配置服務端口號
port:1717
}
在npm run server 啓動後,它是有一種監控機制的(也叫watch)。它能夠監控到咱們修改源碼,並當即在瀏覽器裏給咱們更新。
Webpack打包以後,運行npm run server 發現只有js 可是能夠說明咱們的js打包成功了,可是沒有html,新建html,而且將html打包址dist文件夾。這須要藉助於一個插件html-webpack-plugin
4. Html打包-- html-webpack-plugin
安裝:npm install --save-dev html-webpack-plugin
使用:
const htmlPlugin = require('html-webpack-plugin')
plugins: [
new htmlPlugin({
minify: { removeAttributeQuotes: true },
hash: true,
template: './src/index.html'
})
],
藉助於插件-- html-webpack-plugin,能夠將咱們的html打包址dist文件夾,在使用以前咱們須要先npm安裝
1.require引入插件
2.由於它是一款插件因此咱們須要在plugins中進行這個插件的相關配置。
在配置的時候,須要new一個對象,傳入一些參數,minify:對html文件進行壓縮,removeAttributeQuotes去掉屬性的雙引號,hash爲true是在js後面增長一段hash值,主要是爲了不瀏覽器緩存的,template打包的模版文件
執行webpack,查看發現script有後綴,而且屬性雙引號去掉了。
經過這個插件咱們不只能將html文件打包到dist文件夾還能壓縮html,那麼咱們的js文件怎麼壓縮呢?
5. Js壓縮--uglifyjs-webpack-plugin
若是沒有webpack或gulp的話,可能咱們還須要找一個壓縮軟件或者在線進行壓縮,而在webpack中使用默認已經集成的uglifyjs-webpack-plugin插件輕鬆實現js代碼的壓縮,因爲已經集成,不須要再次安裝。用法:
const uglify = require('uglifyjs-webpack-plugin');
plugins:[
new uglify()
],
執行webpack打包,npm run server發現報錯了,爲何呢?這就涉及到了生產環境和開發環境的區別
由於咱們在開發環境是不須要壓縮js的,可是在生產環境中須要,因此uglifyjs適用於生產環境下的,
因此若是咱們在開發環境中作了生產環境作的事情,就會報錯了
6. Css文件打包-- style-loader,css-loader
安裝:npm install --save-dev css-loader style-loader
使用:
module:{
rules: [{
test: /\.css$/,
use: [ ‘style-loader’, ‘css-loader’ ]
}]
},
Css-loader: 將css文件打包到js中,經常配合style-loader一塊兒使用,將css文件打包並插入到頁面中
Style-loader: 使用<style>將css-loader內部樣式注入到HTML頁面
Loaders是Webpack最重要的功能之一,這也是Webpack如此盛行的緣由。經過使用不一樣的Loader,從而對不一樣的文件格式進行特定處理。
好比說能夠把SASS文件的寫法轉換成CSS,而不在使用其餘轉換工具;把ES6或者ES7的代碼,轉換成大多瀏覽器兼容的JS代碼;把React中的JSX轉換成JavaScript代碼。須要注意的是:全部的Loaders都須要在npm中單獨進行安裝,並在webpack.config.js裏進行配置。Loaders的配置型簡單梳理:
test:用於匹配處理文件的擴展名的表達式,這個選項是必須進行配置的;
use:loader名稱,就是你要使用模塊的名稱,這個選項也必須進行配置,不然報錯;
include/exclude:手動添加必須處理的文件(文件夾)或屏蔽不須要處理的文件(文件夾)(可選);
query:爲loaders提供額外的設置選項(可選)
7.Css中的圖片處理-- url-loader
css中添加背景圖,執行webpack,圖片路徑錯誤
安裝:npm install --save-dev file-loader url-loader
使用:{
test: /\.(png|jpg|gif|jpeg|bmp)/i,
use: [{
loader: 'url-loader',
options: {
limit: 500000
}
}]
}
test:/\.(png|jpg|gif)/是匹配圖片文件後綴名稱
use:是指定使用的loader和loader的配置參數
limit:是把小於500000B的文件打成Base64的格式,寫入JS
url-loader會將引入的圖片編碼,生成dataURl。DataURI是一種提供讓外置資源的直接內嵌在頁面中的方案。至關於把圖片數據翻譯成一串字符。再把這串字符打包到文件中,最終只須要引入這個文件就能訪問圖片了。固然,若是圖片較大,編碼會消耗性能。所以url-loader提供了一個limit參數,小於limit字節的文件會被轉爲DataURl,大於limit的還會使用file-loader進行copy。File-loader能夠解析項目中的url引入(不只限於css),根據咱們的配置,將圖片拷貝到相應的路徑,而且修改打包後文件的引用路徑,使之指向正確的文件。
8. Css分離--extract-text-webpack-plugin
步驟:
1.安裝 npm install --save-dev extract-text-webpack-plugin
2. require引入const extractTextPlugin = require("extract-text-webpack-plugin")
3.Plugins設置: new extractTextPlugin("/css/index.css")
4. 修改css-loader{
test: /\.css$/,
use: extractTextPlugin.extract({
fallback: "style-loader",
use: "css-loader"
})
}
8.Css分離致使圖片路徑錯誤-- publicPath
publicPath:是在webpack.config.js文件的output選項中,主要做用就是處理靜態文件路徑的。
webpack.config.js中聲明對象
var website ={
publicPath:http://127.0.0.1:9090/
}
Output配置
output:{
path:path.resolve(__dirname,'dist'),
filename:'[name].js',
publicPath:website.publicPath
}
publickPath是用來存放靜態文件的,它的值是咱們的本機ip或者devServer配置的IP和端口
9. img標籤添加圖片-- html-withimg-loader
1)在img標籤中直接引入圖片,執行wbbpack命令 —-- 報錯
安裝:npm install --save html-withimg-loader
使用:Webpack.config.js
{
test: /\.(htm|html)$/i,
use: ['html-withimg-loader']
}
2)將圖片打包至image文件夾
options: {
limit: 80000,
outputPath: 'images/'
},
10.消除未使用的CSS --- PurifyCSS
安裝:npm i -D purifycss-webpack purify-css
使用:
1)const PurifyCSSPlugin = require("purifycss-webpack")
2)配置plugins
new PurifyCSSPlugin({
paths: glob.sync(path.join(__dirname, 'src/*.html')),
})
注意:
1. purifycss-webpack 安裝依賴於purify-css,因此須要都安裝
2.這裏咱們用到了glob,glob是node中的模塊,引入glob主要是用來根據某些規則匹配文件的
3.必須要配合extract-text-webpack-plugin(css分離)插件使用
purifycss-webpack 依賴於 purify-css
paths,主要是需找html模板,purifycss根據這個配置會遍歷你的文件,查找哪些css被使用了
Glob:由於咱們須要同步檢查html模板,因此咱們須要引入node的glob對象使用。在webpack.config.js文件頭部引入glob。
11. Less文件的打包和分離-- less-loader
即:將less轉換成css文件進行打包和分離(同css文件分離)
安裝less npm install –save-dev less
使用
{
test: /\.less$/,
use: extractTextPlugin.extract({
fallback: "style-loader",
use: ["css-loader", "less-loader"]
})
}
對於less文件的打包和分離和css文件也是幾乎同樣,只是多了把less轉換成css這一步,下載好less-loader 以後就能夠了。
webpack的強大除了能夠轉換less sass以外還可使用babel轉換es6 es7 jsx等爲普通的js
12支持babel
安裝:npm install --save-dev babel-core babel-loader babel-preset- env
使用: webpack.config.js配置
{
test: /\.(jsx|js)$/,
use: {
loader: ‘babel-loader’,
options: { // 選項
presets: [ // 渲染器
」env", "react"]}
},
exclude: /node_modules/
}
注意:後期隨着項目的增大可能會有不少渲染器,這是這麼寫的話可讀性不太好了,咱們能夠將選項寫在.babelrc文件中。
.webpack.config.js
{
test: /\.(jsx|js)$/,
use: {
loader: ‘babel-loader’
},
exclude: /node_modules/
}
.babelrc
{
"presets": [
"react",
」env"
]
}
11. 抽離第三方類庫
Webpack.config.js
entry:{
entry:'./src/entry.js',
jquery:'jquery',
vue:'vue
'},
new webpack.optimize.CommonsChunkPlugin({
name:[‘jquery’,‘vue’],
filename:"assets/js/[name].js",
minChunks:2
}),
12. 提取公共代碼--CommonsChunkPlugin
步驟:
1.將全部頁面都依賴的庫好比:vue react react-dom等提取到一個單獨的文件,通常叫作base.js(基礎運行環境)
2.剔除各個頁面中的base.js以後的代碼,再找出它們以來的公共部分的代碼,放到common.js
3.將各個頁面生成單獨的文件,這些文件將不包含base.js,common.js中的部分,只包含個頁面單獨須要的部分代碼
具體實現須要藉助於Webpack 內置的用於提取多個 Chunk 中公共部分的插件 CommonsChunkPlugin
大型網站一般會由多個頁面組成,沒個頁面都是一個獨立的單頁應用。可是因爲全部頁面採用的都是相同的技術棧,可能就會致使有不少重複的代碼。若是每一個頁面的代碼都把這些公共的部分包含進去,會形成一些問題。
1)相同資源重複加載,浪費用戶流量和服務器成本;2)頁面須要加載的資源太大,致使頁面首屏加載緩慢,影響用戶體驗
那麼若是咱們能將公共的代碼提取出來,那麼用戶在訪問其中一個網頁的時候,頁面的公共代碼文件就已經被瀏覽器緩存起來,用戶再訪問其餘頁面的時候,公共代碼不會從新加載而是從緩存中獲取。如此,雖然首屏訪問得不到優化,可是後續頁面速度大大提高,而且減小了網絡流量和服務器成本。那麼怎麼提取公共代碼呢???
1.將全部頁面都依賴的庫好比:vue react react-dom等提取到一個單獨的文件,通常叫作base.js(基礎運行環境)
2.剔除各個頁面中的base.js以後的代碼,再找出它們以來的公共部分的代碼,放到common.js
3.將各個頁面生成單獨的文件,這些文件將不包含base.js,common.js中的部分,只包含個頁面單獨須要的部分代碼
在線上文件中,對靜態文件的文件名都附加根據文件內容計算出的hash值,好比base_123a.js,以長期緩存,只要不升級基礎庫的版本,base的內容就不會變化,hash就不會更新,緩存也不會更新,每次更新代碼common.js和js會因文件內容變化而致使hash值被更新。
每次發佈瀏覽器都會使用被緩存的 base.js 文件,而不用去從新下載 base.js 文件。 因爲 base.js 一般會很大,這對提高網頁加速速度能起到很大的效果。
const CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin');
new CommonsChunkPlugin({
chunks: [‘a’, ‘b’], // 從哪些 Chunk 中提取,默認從全部已知chunk獲取
name: 'common’ // 提取出的公共部分造成一個新的 Chunk
})
require('webpack/lib/optimize/CommonsChunkPlugin');
new CommonsChunkPlugin({
chunks: [‘a’, ‘b’], // 從哪些 Chunk 中提取,默認從全部已知chunk獲取
name: 'common’ // 提取出的公共部分造成一個新的 Chunk
})
以上是將a,b的公共代碼提取到了common中,接下來咱們還須要從common中,提取出基礎運行庫。
須要如下操做:
1)首先須要在項目中寫一個base.js來描述項目因此來的模塊,好比:
// 全部頁面都依賴的基礎庫
import 'react';
import 'react-dom';
// 全部頁面都使用的樣式
import './base.css';
2)再修改webpack
module.exports = {
entry: {
base: './base.js'
},
};
new CommonsChunkPlugin({
// 從 common 和 base 兩個現成的 Chunk 中提取公共的部分
chunks: ['common', 'base'], // 把公共的部分放到 base 中 name: 'base'
})
<script src="base.js"></script>
<script src="common.js"></script>
<script src="a.js"></script>
13.打包後如何調試
主要有如下幾種方式:
1)source-map:生成獨立map文件,包含行列信息(信息最詳細完整)
2)cheap-module-source-map:生成獨立map文件,只包含行信息
3)eval-source-map:js文件內生成sourcemap,包含行列信息
4)cheap-module-eval-source-map:就是文件內生成sourcemap,只包含行信息
注意:1)source-map模式下會輸出質量最高最詳細的source Map ,可是會形成構建速度緩慢,在開發過程當中若是頻繁修改,會增長等待時間;
2)source Map會被暴漏出去,因此在生產環境下不建議使用source-map;
3)建議在開發環境下使用cheap-module-eval-source-map或者eval-source-map,開發環境下使用hidden-source-map,可生成最詳細的source Map,但不會暴漏源碼