webpack就是爲打包而生的。css
學習webpack首先須要安裝nodejs,而且做者也強調新版本的nodejs會提升webpack的打包速度。
安裝好node後就能夠在項目命令行中執行下面的代碼html
npm init
而後根據須要設置,也能夠一直回車,固然若是都使用默認配置也能夠node
npm init -y
這樣就能夠在項目中生成package.json
文件了。這樣作的目的就是爲了使項目符合node規範。linux
安裝webpack有兩種方式
1.全局安裝webpack(不推薦)
在命令行中輸入webpack
npm install webpack webpack-cli -g
安裝成功後能夠經過命令 webpack -v
查看是否安裝成功
可是很是不推薦全局方式安裝webpack,由於若是機器上有多項目用不一樣版本webpack就沒法作到兼容。
全局卸載webpackcss3
npm uninstall webpack webpack-cli -g
2.項目內安裝webpack(==推薦==)
命令行進入項目目錄,執行下面命令es6
npm install webpack webpack-cli -D
這種方式安裝成功後沒法經過webpack -v
查看webpack版本信息,由於默認node會查找全局下的webpack。這裏就要經過npx命令查看。web
npx webpack -v
npx命令會在當前項目的node_modules
中找到咱們安裝的webpack正則表達式
3.安裝制定版本webpackchrome
npm install webpack@4.16.0
能夠經過webpack info 查看全部版本
安裝好webpack後就能夠開始打包咱們的項目代碼了,如咱們項目中有一個xxx.js
文件。
npx webpack xxx.js
這樣就會將某一個js文件進行打包,打包後的文件就存放在項目根目錄的dist文件夾中。這樣就是webpack最基礎的打包方式,使用的也是webpack默認的配置。若是想要更多的功能就要在webpack.config.js
文件中進行配置
在項目根目錄中新建一個webpack.config.js
文件。
const path = require('path'); module.exports = { mode: 'production', // 打包模式,production爲生產模式,development爲開發模式 開發模式下js不會被壓縮 // entry: 指定入口文件, entry: { // 打包輸出兩個文件 home: './src/index.js', index: './src/index.js' }, output: { // 輸入配置 publicPath:'http://cdn.com.cn',// 指定打包的文件前綴地址 filename:'[name].js', // 打包後的文件名,可使用placeholder佔位符方式,[name]獲取到entry中配置的名稱 path: path.resolve(__dirname, 'dist') // 打包好的文件夾,默認就是dist } }
這就是最近本的打包配置,指定的打包模式,入口,輸出配置等。
配置好後就能夠經過
npx webpack
直接運行,不用再寫具體文件,而是經過配置的入口去找到指定文件。webpack.config.js
是webpack默認的配置文件,固然也能夠手動修改
命令行執行以下面命令便可,npx webpack --config webpackconfig2.js
在平時開發的時候可能不多有人用到npx webpack
這種命令進行打包,這是由於在package.json
文件中對打包命令進行了簡化,在scripts中添加以下代碼
"scripts": { "bundle": "webpack" },
這樣改寫後執行npm run bundle
至關於執行了webpack打包命令。
在scripts中使用webpack會優先在項目的node_modules中找webpack。
咱們以前在安裝webpack的時候,安裝了一個webpack-cli
,這個webpack-cli
包的做用就是讓咱們能夠在命令行中運行webpack命令(npx webpack
等命令)。
webpack的做用就是打包,可是webpack只能識別js文件,若是咱們的js文件中引入了樣式,或者嘗試打包一個css文件、圖片文件等,那麼webpack就會報錯。由於webpack不知道如何處理這樣的文件。這時webpack就須要一個東西幫他處理,就是loader。
==loader就是幫助webpack打包不能識別的文件==
css-loader & style-loader
const path = require('path'); module.exports = { mode: …… entry: ……, output: ……, module:{ rules:[ { test: /\.css$/, use: ['style-loader','css-loader'] } ] } }
想打包css文件就要安裝style-loader和css-loader。
npm install style-loader css-loader -D
rules
數組中就是不少打包規則,經過正則表達式匹配到css文件,而後告訴webpack一旦遇到css文件就使用style-loader
和css-loader
處理。css-loader
的做用是幫助webpack識別css。分析文件關係,而後合併。style-loader
的做用是獲得css-loader分析出來的結果,將css掛載到html-header-style中。
==因此loader的調用是有順序的,順序是從後向前==,先執行css-loader再執行style-loader。
sass-loader
打包sass文件須要用到sass-loader。首先安裝sass-loader和node-sass。npm i sass-loader node-sass -D
而後改動一下rules
rules:[ { test: /\.css$/, use: [ 'style-loader', { loader: 'css-loader', options: { importLoaders: 1, modules: true // 默認false,引入的css屬於全局的樣式,開啓true後,css變爲模塊化,引入css時能夠經過style.xxx } }, 'sass-loader' ] } ]
sass-loader的調用必定要在css-loader
以前,因此要放到數組最後。可是若是一個scss文件中經過import了另外一個scss文件,那麼在打包第二個scss文件就會直接走到css-loader
,致使打包失敗。因此要在css-loader
的options
中加入importLoaders
,表示走css-loader
前還要走另一個loader。
postcss-loaderpostcss-loader
能夠自動添加css3前綴,須要新建一個postcss.config.js
文件,而且要安裝插件, npm i autoprefixed -D
將postcss-loader放到rules中sass-loader
以前執行,也就是數組最後。
postcss.config.js
module.exports = { plugins: [require('autoprefixer')] }
這樣咱們在打包css代碼時,就會自動添加css3前綴。由於autoprefixer中內置了瀏覽器兼容表,默認>5%兼容。
file-loader & url-loader
先安裝npm i file-loader -D
。打包圖片文件以下
rules: [ { test: /\.(jpg|png|gif)$/, use: { loader: 'file-loader', option: { name: '[name]_[hash].[ext]', outputPath: 'images/' } } } ]
name命名使用placeholder-佔位符
,不指定則打包後的文件是隨機生成的名字。
對於特別小的圖片,可使用url-loader
打包成base64格式放到js文件中。
先安裝npm i url-loader -D
,file-loader的功能url-loader一樣也能夠實現,經過配置大小限制,若是超過則使用傳統方式打包,不然就使用base64方式打包,十分方便。
rules: [ { test: /\.(png|jpg|gif)$/, use:{ loader: 'url-loader', options:{ name: '[name]_[hash].[ext]', outputPath: 'images/', limit: 2048 // 限制文件大小小於2048字節,使用base64方式打包 } } } ]
安裝babel-loader 和 babel/core 包。npm i babel-loader @babel/core -D
babel-loader是幫助webpack打包的工具
babel/core是babel的核心庫。可讓babel識別js中的語法,將js語法轉換爲AST抽象語法樹。
添加babel-loader分析js語法,打通babel和webpack,同時還須要藉助其餘babel模塊才能將es6 轉換爲 es5。安裝babel/preset-envnpm i @babel/preset-env -D
如今就能夠將es6轉換爲es5了,可是一些方法在低版本的瀏覽器中依然不支持。還須要藉助polyfill模塊。npm i @babel/polyfill -D
而後在業務代碼中引入polyfillimport "@babel/polyfill"
而後改寫webpack.config.js
rules: [ { test: /\.js$/, exclude: /node_modules/, // 排除node_modules中的代碼 loader: 'babel-loader', options:{ presets:[["@babel/preset-env"],{ targets:{ chrome: ">67" // 能夠指定兼容瀏覽器版本 }, // 當使用polyfill的時候,會將全部特性都加入,而不是根據業務代碼決定加什麼,致使打包後的文件過大。因此經過以下配置解決這個問題,根據業務代碼的須要將使用的特性打包進去 useBuiltIns: 'usage' }] } } ]
如今就能夠正常打包es6的代碼了。不過依然會有一個潛在的問題,就是polyfill再注入方法的時候經過全局變量的形式完成的,會污染全局環境,不適用組件打包。
解決辦法:npm i @babel/plugin-transform-runtime @babel/runtime @babel/runtime-corejs2 -D
在babel options中添加plugins配置。
rules: [ { test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader', options:{ // 庫代碼使用此配置,解決polyfill的問題 "plugins": [["@babel/plugin-transform-runtime"], { "corejs": 2, "helpers": true, "regenerator": true, "useESModules": false }] } } ]
補充:options內的配置能夠單獨放到.babelrc文件中
plugin相似一些框架中的生命週期函數,在打包特定的時間點觸發去作一些事情。
HtmlWebpackPlugin
如html-webpack-plugin是在打包結束後。安裝這個插件。npm i html-webpack-plugin -D
HtmlWebpackPlugin插件會在打包結束後,自動生成一個html文件,並把打包生成的js自動引入到這個html中,html中沒有標籤。也能夠經過模版template,這樣在生成html文件時會以配置的html文件爲模版生成。
const path = require('path'); module.exports = { mode: …… entry: ……, output: ……, module: ……, plugins: [ new HtmlWebpackPlugin({ // 根據模版生成html文件 template: 'src/index.html' }) ] }
CleanWebpackPlugin
CleanWebpackPlugin插件會在打包前將dist目錄刪除(非官方)cnpm i clean-webpack-plugin -D
module.exports = { mode: …… entry: ……, output: ……, module: ……, plugins: [ // 從新打包先刪除dist目錄 new CleanWebpackPlugin(['dist']) ] }
sourceMap 是一個映射關係,他知道dist目錄下main.js文件出錯位置,對應的是src下的index.js文件的位置。在webpack.config.js中添加devtool配置。
module.exports = { mode: …… devtool: 'none' }
設置devtool: 'none'
,js報錯只會提示在打包後的js文件中,在開發的時候定位錯誤就變得異常困難。
設置devtool: 'source-map'
,js報錯會顯示在原來的文件中,由於在打包後的目錄中會生成一個map.js文件,裏面存的就是映射關係。報錯時經過映射關係找到原文件。
設置devtool: 'inline-source-map'
,inline這種方式不會生成map文件,而是生成base64字符串保存在打包後的js文件底部。
設置devtool: 'cheap-source-map'
,如不設置cheap,報錯信息會具體到行列,致使映射關係複雜,耗費性能。加上cheap解決這個問題,同時不去處理第三方代碼,只處理業務代碼。到一些業務須要將咱們本身寫的模塊或者第三方代碼進行處理。那就要用到module。
設置devtool: 'cheap-module-source-map'
,設置module後解決cheap不處理第三方模塊的問題。
設置devtool: 'cheap-module-eval-source-map'
,設置eval後,不會生成map文件,也不會有base64編碼的字符串,而是改變代碼的執行方式,經過sourceURL指向原文件。性能最好。
==開發環境最佳實踐==:devtool: 'cheap-module-eval-source-map'
==生產環境最佳實踐==:devtool: 'cheap-module-source-map'
每次修改後都要從新手動打包,這樣很是浪費時間。有三種方式解決這個問題
1.在package.json中添加"watch": "webpack --watch"
scripts:{ "watch": "webpack --watch" }
打包的時候運行命令npm run watch
這時webpack就會監聽要打包的文件,若是文件變化就會從新打包。
2.配置 devServer
安裝dev-server 執行。npm i webpack-dev-server -D
在package.json中添加配置
scripts:{ "start": "webpack-dev-server" }
打包的時候運行命令npm run start
同時也能夠在webpack.config.js中添加配置,
module.exports = { …… devServer: { contentBase: './dist', // 打包文件目錄 open: true, // 是否自動打開瀏覽器 prot: 8080 // 啓動服務端口 } }
==webpack-dev-server 打包後不會生成dist目錄,而是在內存中。提高打包速度==
使用dev-server時能夠搭配使用Hot Module Replacement (熱模塊替換)
引入HotModuleReplacementPlugin插件,可開啓hmr功能,hmr能夠熱更js、css等代碼。
module.exports = { …… devServer: { contentBase: './dist', // 打包文件目錄 open: true, // 是否自動打開瀏覽器 prot: 8080, // 啓動服務端口 hot: true, // 開啓hmr hotOnly: true // 阻止瀏覽器自動刷新 }, plugins: [ new webpack.HotModuleReplacementPlugin() ], }
3.本身編寫node服務
本身編寫服務如server.js ,在package.json中配置server命令"server": "node server.js"
,至關於在node中使用webpack
打包時執行命令npm run server
便可。
webpack基礎用法就是這些,文中涉及到的內容足夠知足一個小型項目的打包需求。基礎用法熟練掌握後,能夠經過閱讀webpack官方文檔進行更詳細的打包配置。