官網給出的概念是:本質上,webpack 是一個現代 JavaScript 應用程序的靜態模塊打包器(module bundler)。當 webpack 處理應用程序時,它會遞歸地構建一個依賴關係圖(dependency graph),其中包含應用程序須要的每一個模塊,而後將全部這些模塊打包成一個或多個 bundle。javascript
爲何使用webpack,這應該和前端的發展是有關係的,由於計算機網絡的飛速發展,致使前端也在迅猛發展,最初的實踐方案已經不能知足咱們的需求,加上新的技術和新思想框架的產生,爲了節省開發的成本和效率,因此webpack的產生是一個必然的結果css
gulp和grunt的操做都是流式的,可是gulp是基於內存流,grunt是基於文件流,因此相對來講,gulp的性能要高於grunt,並且他們都是須要定義一個個任務,而後自動將一個個任務執行。,而webpack是模塊化的組織,模塊化的依賴,而後模塊化的打包,相對來講,webpack更強調模塊化開發,而那些文件合併壓縮、預處理等功能,不過是他的附帶功能。並且如今相對於前二者,webpack的插件也更爲豐富html
Rollup是在webpack流行後出現的替代品,Rollup和webpack相似,可是專一於ES6模塊打包,相比webpack,Rollup功能和插件都不如webpack完善,不過Rollup在用於打包JavaScript庫時比webpack更加有又是,由於其打包的代碼更小更快。但也由於功能不完善,不少場景找不到現成的解決方案。前端
由於如今webpack已經更新到到4.0+了,因此本篇就直接按4.0+的來說好了vue
也叫初始化,能夠手動建立,也可使用命令自動建立,建議是命令建立java
npm init
而後本身配置文件名、版本號等信息node
若是想要快捷安裝的話,使用下面的命令(-y 表示使用默認參數)webpack
npm init -y
注意:1.package文件裏面的name屬性的值若是用駝峯式命名的話,會報警告web
2. 經過文件名咱們就知道package.json文件是json的對象,因此語法確定是嚴格按照json的格式,不能添加註釋,屬性和值只能用雙引號不能用單引號,不能多添加逗號 vue-cli
webpack能夠直接使用npm安裝,由於咱們須要使用webpack這個命令,因此必需要全局安裝
npm i webpack -g
而後在項目中安裝
npm i webpack -S
注意點:webpack 4+以上的,都須要安裝webpack-cli,因此還須要安裝webpack-cli
npm i webpack-cli -S
按着上面的步驟安裝好以後,等你配置好webpack.config.js文件在終端輸入webpack時你可能會遇到下面這個問題
解決辦法:全局安裝一下webpack-cli便可
npm i webpack -g
到此安裝步驟就已經搞定了,下面教你們如何使用
建立src文件夾、public文件夾和webpack.config.js文件
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> </head> <body> <div id="app"></div> <script src="bundle.js"></script> </body> </html>
module.exports = { mode:'development', // 當前的開發模式 entry: __dirname + "/src/main.js",// 入口文件 output: { path: __dirname + "/dist",// 打包後的文件存放的地方 filename: "bundle.js" // 打包後輸出文件的文件名 } }
這些基礎配置完以後,咱們在項目的終端輸入
webpack
就會輸出一下信息
看到這樣的信息的話,那麼恭喜你,你的第一個webpack項目完成了
此時你會看到文件夾目錄下會多了一個dist文件夾
OK,上面的文件寫法咱們還能夠作一下改進,例如文件的文件路徑問題,咱們須要寫成的是絕對路徑,node裏面有自帶一個path模塊,咱們能夠換成下面的寫法
const path=require('path'); module.exports={ mode:'development', // 入口文件 entry:'./src/main.js', // 出口文件 output:{ filename:'bundle.js', path:path.resolve(__dirname,'public') } }
上面這個是單個入口文件的寫法,有單個入口的話,那確定是有多個入口的啊,下面這段就是多個入口文件的寫法:
const path=require('path'); module.exports={ mode:'development', // 多個入口的話,在這邊配置 entry:{ index:'./src/js/1.js', admin:'./src/js/index.js', }, output:{ // 出口的名字就是上面entry定義的名字,上面定義的是index和admin,打包後在dist文件夾裏面的js就是index.min.js和admin.min.js filename:'[name].js', path:path.resolve(__dirname,'dist') } }
在出口文件處的filename中,就不須要寫死bundle.js這些了,直接用name變量來接收,打包出來後的文件名字來源於entry中入口文件中的定義的鍵,如上面的就是index和admin
webpack自己只能處理javascript,若是要處理其餘類型的文件的話,就須要使用loader來進行轉換。下面我就列舉了咱們常常用的幾個
css-loader---->引入css文件
咱們能夠在src文件夾裏面新建一個css文件夾,而後在裏面新建一個main.css文件。在webpack中,全部的文件都是一個模塊,因此要使用這個css文件,就必需要先引入
在main.js文件中引入css文件
import './css/main.css'
而後在終端輸入webpack後發現報錯啦
這個時候呢,安裝一下css須要使用到的loader,而後在配置一下在試試
處理css須要使用到兩個loader,css-loader和style-loader
npm install --save-dev style-loader css-loader
module.exports={ // 當前的開發模式 // 開發模式:development,會保留咱們開發時的一些必要信息 // 生產模式:production會盡力壓縮,能壓多大就壓多大 // none:什麼也不幹,就只是打包 mode:'development', entry:'./src/js/main.js', output:{ filename:'bundle.js', path:path.resolve(__dirname,'dist') }, // 添加的module裏面的rules module:{ rules:[ { test:/\.css$/, // webpack的loader執行順序是反的,先執行css-loader後執行style-loader use:[ 'style-loader', 'css-loader' ] } ] } }
說明: loader都是在module裏面的rules中配置的,rules是一個數組配置規則,該規則告訴webpack符合test的文件,使用use後面的loader處理,因此該規則就是對全部的.css文件使用css-loader、style-loader
注意點:loader的執行順序是由右向左執行的,先執行css-loader後在執行style-loader
在終端輸入webpack後,提示下面的信息就是成功啦
資源 | loader名 |
圖片 | file-loader |
sass | saa-loader |
less | less-loader |
babel | babel-loader |
字體 | file-loader和url-loader |
npm install --save-dev file-loader
rules:[ { test:/\.css$/, // webpack的loader執行順序是反的,先執行css-loader後執行style-loader use:[ 'style-loader', 'css-loader' ] }, + { + test: /\.(png|svg|jpg|gif)$/, + use: [ + 'file-loader' + ] + } + ]
{ test: /\.(woff|woff2|eot|ttf|otf)$/, use: [ 'file-loader' ] }
npm install --save-dev less-loader less
{ test: /\.less$/, use: [{ loader: "style-loader" // creates style nodes from JS strings }, { loader: "css-loader" // translates CSS into CommonJS }, { loader: "less-loader" // compiles Less to CSS }] }
npm install sass-loader node-sass --save-dev
{ test: /\.scss$/, use: [ "style-loader", // creates style nodes from JS strings "css-loader", // translates CSS into CommonJS "sass-loader" // compiles Sass to CSS, using Node Sass by default ] }] }
npm install -D babel-loader @babel/core @babel/preset-env
{ test: /\.(js|jsx)$/i, exclude: /node_modules/, use: { loader: 'babel-loader', options: { presets: ['@babel/preset-env'] } } }
module:{ rules:[ // 加載css { test:/\.css$/, // webpack的loader執行順序是反的,先執行css-loader後執行style-loader use:[ 'style-loader', 'css-loader' ] }, // 加載圖片 { test: /\.(png|svg|jpg|gif)$/, use: [ 'file-loader' ] }, // 加載字體 { test: /\.(woff|woff2|eot|ttf|otf)$/, use: [ 'file-loader' ] }, // 加載less { test: /\.less$/, use: [{ loader: "style-loader" // creates style nodes from JS strings }, { loader: "css-loader" // translates CSS into CommonJS }, { loader: "less-loader" // compiles Less to CSS }] }, // 加載sass { test: /\.scss$/, use: [ "style-loader", // creates style nodes from JS strings "css-loader", // translates CSS into CommonJS "sass-loader" // compiles Sass to CSS, using Node Sass by default ] }, // 加載base64 { test: /\.(png|jpg|gif)$/i, use: [ { loader: 'url-loader', options: { limit: 8192 // 當圖片小於8192K以後轉爲base64 } } ] }, // 加載數據 { test: /\.(csv|tsv)$/, use: [ 'csv-loader' ] }, { test: /\.xml$/, use: [ 'xml-loader' ] },
// 加載ES6以上版本 { test: /\.(js|jsx)$/i, exclude: /node_modules/, use: { loader: 'babel-loader', options: { presets: ['@babel/preset-env'] } } } ] }
插件(Plugin)是用來擴展webpack功能的,webpack能夠實現loader所不能實現完成的複雜功能,使用plugin豐富的自定義API以及生命週期事件,能夠控制webpack打包流程的每一個環節,實現webpack的自定義功能擴展
html-webpack-plugin
能夠根據你設置的模板,在每次運行後生成對應的模板文件,同時所依賴的 CSS/JS 也都會被引入,若是 CSS/JS 中含有 hash 值,則
html-webpack-plugin
生成的模板文件也會引入正確版本的 CSS/JS 文件。
npm i html-webpack-plugin -D
const path=require('path'); const HtmlPlugin=require('html-webpack-plugin'); module.exports = { entry: __dirname + "/src/main.js",//已屢次說起的惟一入口文件 output: { path:path.resolve(__dirname, './dist'),//打包後的文件存放的地方 filename: "bundle.js"//打包後輸出文件的文件名 }, module:{ rules:[ // 加載css { test:/\.css$/, // webpack的loader執行順序是反的,先執行css-loader後執行style-loader use:[ 'style-loader', 'css-loader' ] }, // 加載圖片 { test: /\.(png|svg|jpg|gif)$/, use: [ 'file-loader' ] }, // 加載字體 { test: /\.(woff|woff2|eot|ttf|otf)$/, use: [ 'file-loader' ] }, // 加載less { test: /\.less$/, use: [{ loader: "style-loader" // creates style nodes from JS strings }, { loader: "css-loader" // translates CSS into CommonJS }, { loader: "less-loader" // compiles Less to CSS }] }, // 加載sass { test: /\.scss$/, use: [ "style-loader", // creates style nodes from JS strings "css-loader", // translates CSS into CommonJS "sass-loader" // compiles Sass to CSS, using Node Sass by default ] }, // 加載base64 { test: /\.(png|jpg|gif)$/i, use: [ { loader: 'url-loader', options: { outputPath: 'images/', limit: 8*1024 // 當圖片小於8192K以後轉爲base64 } } ] }, // 加載數據 { test: /\.(csv|tsv)$/, use: [ 'csv-loader' ] }, { test: /\.xml$/, use: [ 'xml-loader' ] }, { test: /\.(js|jsx)$/i, exclude: /node_modules/, use: { loader: 'babel-loader', options: { presets: ['@babel/preset-env'] } } } ] }, plugins: [ new HtmlPlugin(), ] }
配置完以後,你會看到在dist文件夾下面會多了一個index.html文件
若是你想打包一個固定的模板的話,你能夠在實例化插件的時候添加參數配置
plugins: [ new HtmlPlugin({ template: './public/index.html' // 模板的地址 }), ]
在webpack中,默認css文件是一塊兒打包進js文件裏面去的,若是你但願打包後css在單獨的文件中的話,name你就須要MiniCssExtractPlugin(ExtractTextPlugin在webpack4+版本中已經廢棄掉了,若是使用4如下的版本的話,能夠自行官網查api,也是相似的寫法的)這個plugin了
npm i mini-css-extract-plugin -D
const path=require('path'); const HtmlPlugin=require('html-webpack-plugin'); const MiniCssExtractPlugin=require('mini-css-extract-plugin'); module.exports = { entry: __dirname + "/src/main.js",//已屢次說起的惟一入口文件 output: { path:path.resolve(__dirname, './dist'),//打包後的文件存放的地方 filename: "bundle.js"//打包後輸出文件的文件名 }, module:{ rules:[ // 加載css { test:/\.css$/, // webpack的loader執行順序是反的,先執行css-loader後執行style-loader use:[ { loader: MiniCssExtractPlugin.loader, }, 'css-loader' ] }, ] }, plugins: [ new HtmlPlugin({ title:'webpack test', template:path.join(__dirname, './public/index.html') }), new MiniCssExtractPlugin({ filename:'[name].css', chunkFilename:'[id].css' }) ] }
配置完成後在終端輸入webpack,你會發現dist文件夾裏面會多了一個main.css文件(前面已經在src目錄下的css文件夾中新建了main.css,並導入到了main.js中),到這,css就已經抽離出來啦
咱們平時開發的時候,例如gulp都會區分開發環境仍是生產環境,這兩個環境下所要配置的一些參數確定是要不同的,並且咱們在開發環境下,並不須要打包。在這種狀況下,咱們要這麼去區分運行環境呢?webpack提供了一個webpack-dev-server工具給咱們搭建本地運行環境。有了這個插件以後,咱們能夠配置命令腳本快捷運行
npm i webpack-dev-server -D
"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "start": "webpack-dev-server ", "dev": "webpack-dev-server ", "build": "webpack" }
經過上面的代碼,咱們能夠知道,在見解環境下才要運行項目環境,若是打包的時候就用build的那個命令來充當生產環境
npm run start // 或 npm run dev
生產環境下的話,咱們須要作的是打包的工做
npm run build
瞭解npm 命令的話,咱們應該知道,在npm的命令腳本中,咱們是能夠添加參數的,咱們能夠經過添加參數來設置一下在開發環境下自動在默認瀏覽器中打開項目
默認的端口是8080端口
修改默認端口
嗯,有些時候咱們的端口可能被其餘項目佔用着,因此爲了項目得以運行,確定是要改一下端口的啊。咱們能夠在配置命令腳本的時候添加參數--port 端口號
"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "start": "webpack-dev-server --open --port 3000", "dev": "webpack-dev-server ", "build": "webpack" },
此時的端口就已經改成了3000端口了
咱們每次修改完都要重啓一下運行環境,這樣的操做效率過低了,並且很浪費時間,咱們要怎麼作到每次修改完他都會自動更新呢,固然是有解決方法的啊,添加--hot參數便可
"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "start": "webpack-dev-server --open --port 3000 --hot", "dev": "webpack-dev-server ", "build": "webpack" }
開發的時候區分環境更項目配置的,能夠查看個人上一篇的使用webpack構建簡易的vue-cli框架的筆記(http://www.javashuo.com/article/p-weqplrvm-w.html)
有時候咱們在開發的時候須要作性能優化的時候,就確定想要知道在編譯過程當中哪些步驟耗時最長。這個時候咱們可使用--profile
"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "start": "webpack-dev-server --open --port 3000 --hot --profile", "dev": "webpack-dev-server ", "build": "webpack" }