成爲一個全棧工程師,前端是必不可少的,這位前端構建工具webpack是一門必修的技術。javascript
在學習webpack以前,先熟悉一下npm工具:https://www.runoob.com/nodejs/nodejs-npm.htmlcss
什麼是webpack?html
webpack能夠打包全部的樣式,腳本,表,資源,生成一個或多個bundle,webpack 可以處理 JS 文件的互相依賴關係,可以處理JS的兼容問題,把高級的、瀏覽器不是別的語法,轉爲低級的瀏覽器能正常識別的語法。前端
官方文檔:https://www.webpackjs.com/concepts/java
example參考:https://github.com/lemonzoey/webpack-demo node
1 初始化項目 npm init , 建立src,dist目錄,在src下創建main.js,index.htmljquery
2 安裝依賴包jquery : npm install jquerywebpack
3 安裝webpack : npm install --save-dev webpackgit
mkdir webpack-study && cd webpack-study
npm init -y
npm install webpack webpack-cli --save-dev
4 編寫項目github
main.js是項目的JS入口文件
// 這是 main.js 是咱們項目的JS入口文件 // 1. 導入 Jquery // import *** from *** 是ES6中導入模塊的方式 // 因爲 ES6的代碼,過高級了,瀏覽器解析不了,因此,這一行執行會報錯 import $ from jquery // const $ = require('jquery') $(function () { $('li:odd').css('backgroundColor', 'yellow') $('li:even').css('backgroundColor', function () { return '#' + 'D97634' }) })
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <!-- 由於 main 中的代碼,涉及到了ES6的新語法,可是瀏覽器不識別 --> <!-- <script src="./main.js"></script> --> <!-- 經過 webpack 這麼一個前端構建工具, 把 main.js 作了一下處理,生成了一個 bundle.js 的文件 --> <script src="../dist/bundle.js"></script> </head> <body> <ul> <li>這是第1個li</li> <li>這是第2個li</li> <li>這是第3個li</li> <li>這是第4個li</li> <li>這是第5個li</li> <li>這是第6個li</li> <li>這是第7個li</li> <li>這是第8個li</li> <li>這是第9個li</li> <li>這是第10個li</li> </ul> </body> </html>
5 webpack編譯打包main.js
webpack src/main.js --output dist/bundle.js
或者能夠在根目錄下建立 webpack.config.js
const path = require('path'); module.exports = { entry: './src/main.js', //入口 表示要打包的文件 output: { path: path.join(__dirname, './dist'),// 指定輸出路徑 filename: 'my-first-webpack.bundle.js' } };
再執行: webpack
固然執行命令能夠交給npm管理,須要在package.json上添加
再執行命令 npm run build
加載css樣式
1 安裝資源加載器
npm install --save-dev style-loader css-loader
2 添加樣式文件
3 添加webpack配置文件css資源加載
const path = require('path'); module.exports = { entry: './src/main.js', //入口 表示要打包的文件 output: { path: path.join(__dirname, './dist'),// 指定輸出路徑 filename: 'bundle.js' }, module:{ rules:[ { test:/\.css$/, use:[ 'style-loader', 'css-loader' ] } ] } };
4 修改main.js 添加css文件,使得資源文件被加載到bundle.js中
其餘加載圖片,字體,數據等資源,相同的操做步驟,可參考官方文檔.
若是index.html中引用了多個bundle文件,若是這些bundle文件名稱發生改變,而index.html還引用原來的bundle文件名,則會出錯。
這個plugin就是讓指定的html每次build的時候生成一個新的html文件,該文件引用最新的bundle文件。
const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { entry: { // 存在多個入口文件 main: './src/main.js', print: './src/print.js' }, //入口 表示要打包的文件 output: { // 也輸出多個bundle.js文件 path: path.join(__dirname, './dist'),// 指定輸出路徑 filename: '[name].bundle.js' }, plugins: [ new HtmlWebpackPlugin({ title: 'new Document' // title=new Document的html文件,會從新加載生成一個新的html }) ], module: { rules: [ { test: /\.css$/, use: [ 'style-loader', 'css-loader' ] } ] } };
clean-webpack-plugin
清理/dist 文件夾
1 若是某個js發生錯誤,但願可以定位到具體的js中,能夠在webpack.config.js中添加以下選項
webpack-dev-server使用
npm install --save-dev webpack-dev-server
webpack.config.js
devServer: { contentBase: './dist' }
package.json
"start": "webpack-dev-server --open"
執行命令 npm run start
該功能容許運行時更新各個模塊,而不是全量刷新.
webpack.config.js
const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const CleanWebpackPlugin = require('clean-webpack-plugin'); + const webpack = require('webpack'); module.exports = { entry: { - app: './src/index.js', - print: './src/print.js' + app: './src/index.js' }, devtool: 'inline-source-map', devServer: { contentBase: './dist', + hot: true }, plugins: [ new CleanWebpackPlugin(['dist']), new HtmlWebpackPlugin({ title: 'Hot Module Replacement' }), + new webpack.NamedModulesPlugin(), + new webpack.HotModuleReplacementPlugin() ], output: { filename: '[name].bundle.js', path: path.resolve(__dirname, 'dist') } };
package.json
"start": "webpack-dev-server --hotOnly"
若是全部代碼都不包含反作用,那麼能夠刪除一些未用到的export導出代碼,
package.json
{ "name": "your-project", "sideEffects": false }
若是有反作用,能夠指定文件{
"name": "your-project", "sideEffects": [ "./src/some-side-effectful-file.js", "*.css" ] }
1 建立多個環境配置文件
+|- webpack.common.js
+ |- webpack.dev.js
+ |- webpack.prod.js
2 安裝
npm install --save-dev webpack-merge 用於合併多個配置文件 merge()
3 如開發配置
+ const merge = require('webpack-merge'); + const common = require('./webpack.common.js'); + + module.exports = merge(common, { + devtool: 'inline-source-map', + devServer: { + contentBase: './dist' + } + });
4 npm script
實際上編譯出多個bundle代碼,且公共部分提取到一個文件。避免重複模塊引用到各個bundle中
動態導入
動態import模塊,使得調用的時候編譯出bundle文件。
實際上就是每一次文件bundle文件變動,可以變動文件名,使得客戶端可以感知文件的變化。
只須要在webpack配置output的時候,文件名上添加hash段
output: {
- filename: 'bundle.js', + filename: '[name].[hash].js', path: path.resolve(__dirname, 'dist') }
提取模板manifest
...
new webpack.HashedModuleIdsPlugin() // 防止標識符moduleId的改變,致使無修改bundle刷新 // 用於生產環境 ], optimization: { splitChunks: { cacheGroups: { commons: { name: "vendor", // 生成共享模塊bundle的名稱 chunks: "initial",//」initial」, 「async」 和 「all」. 分別對應優化時只選擇初始的chunks,所須要的chunks 仍是全部chunks 。 minChunks: 2 //共享模塊的chunks的最小數目 ,默認值是1 } } } }, optimization: { splitChunks: { cacheGroups: { commons: { name: "manifest", chunks: "initial", minChunks: 2 } } } },
webpack --env.NODE_ENV=local --env.production --progress
在項目中構建路徑值,publicPath 也會在服務器腳本用到,以確保文件資源可以在 http://localhost:8080 下正確訪問