最近因爲學習需求,手擼了個簡單的SPA框架並使用Webpack4作打包和預覽調試,因爲沒有怎麼系統學習過Webpack因此遇到坑挺多,索性直接開始從頭學一波順便記錄下來.
寫Webpack文章不寫版本都是耍流氓,這篇文章基於當下最新的 webpack v4.22.0 以及 webpack-cli v3.1.2 編寫.
本章以 環境搭建 -> 練習1 -> 理論學習 -> 練習2
的步驟進行:html
Tip:全過程將記錄在Github倉庫 webpack-stepbystep 中,邊看文章邊看commit學習食用效果更佳喲~node
想要學習Webpack的小夥伴大概都知道Webpack是用來打包的,嗯暫時知道這些就足夠了,立刻來開始第一次打包的體驗吧~webpack
開始實戰確定要建立工程的,使用下面的命令開始(須要 Node.js ):git
mkdir webpack-stepbystep cd webpack-stepbystep npm init -y npm i -D webpack webpack-cli webpack -v webpack-cli -v
上面的命令語句分別是:github
本文的環境是webpack v4.22.0 & webpack-cli v3.1.2, 最後兩句版本檢查若是運行失敗的話,能夠考慮使用全局方式安裝 Webpack & Webpack-cli, 以前在Windows上開發的時候遇到過這個問題, 全局安裝命令以下:web
npm install -g webpack webpack-cli webpack -v webpack-cli -v
其餘安裝問題暫且按下不表, 可自行參考 Installation. npm
完成以上項目環境搭建以後,項目的文件結構大體以下所示:json
webpack-stepbystep └─ node_modules └─ package-lock.json └─ package.json
項目環境搭建至此所有完成, 以上環境搭建的項目提交爲init(project): finish base enviroment setup, 立刻進入實戰環節.數組
首先添加index.html
& src/index.js
, 項目的文件結構大體以下所示:瀏覽器
webpack-stepbystep └─ node_modules └─ src └─ index.js └─ index.html └─ package-lock.json └─ package.json
編輯index.html
, 其中用script引用了第三方工具庫 lodash:
<!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>Started</title> <script src="https://unpkg.com/lodash@4.16.6"></script> </head> <body> <body> <script src="./src/index.js"></script> </body> </body> </html>
而後編輯 src/index.js
, 代碼中的 _
即對lodash庫的引用:
function component () { let element = document.createElement('div'); element.innerHTML = _.join(['Hello', 'Webpack'], ''); return element; } document.body.appendChild(component());
能夠看出 index.html
中的兩個 <script>
之間存在這隱式依賴的關係, 即 index.js
默認全局存在lodash. 這種刀耕火種時期的寫法存在三個問題:
有錯就要改,因此咱們開始使用現代方案來對當前項目進行修改~
至此項目提交爲 feat(project): add index.html & index.js with implicit dependencies .
現代的思想是用npm將庫下載到本地,在js中顯示聲明依賴並調用,最後用Webpack完成打包,瞭解了以後就開始吧:
./src/index.js
爲起點開始構建,獲取依賴並完成打包到./dist/main.js
. (文章第三節」學習:Webpack概念「將會介紹);第一步、將依賴安裝到項目中. 以後 Webpack 會將依賴一塊兒打包到main
防止依賴丟失形成的運行問題:
npm i -S lodash
第二步、在文件 index.js
頂部用import顯式聲明依賴. 方便依賴的查找的同時明確了項目所需的依賴:
import _ from 'lodash'; function component () { let element = document.createElement('div'); element.innerHTML = _.join(['Hello', 'Webpack'], ''); return element; } document.body.appendChild(component());
第三步、執行打包. 打開終端在當前項目下運行 webpack
,運行成功以後發現當前項目目錄多出了 dist
文件夾,項目的文件結構大體以下所示:
webpack-stepbystep └─ dist └─ main.js └─ node_modules └─ src └─ index.js └─ index.html └─ package-lock.json └─ package.json
完美~Webpack的打包操做如今已經完成了!只剩完成最後一步就能夠完美運行程序了!
第四步、按照 Webpack 的默認規則修改 index.html
中的引用. 先刪除兩個 <script>
標籤,再添加對於Webpack生成 main.js
的引用;
<!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>Started</title> </head> <body> <body> <script src="main.js"></script> </body> </body> </html>
因爲 Webpack 的默認規則只能打包js,因此咱們先用一下比較粗暴的手段,直接把index.html
複製一份,放到打包完生成的dist
文件夾下. 在瀏覽器運行該index.html
.
WOW! 瀏覽器出現了 Hello Webpack的字樣,運行成功!Webpack首戰成功結束~接下來來了解一下Webpack的概念.
至此項目提交爲 feat(project): combat:project bundle without configuration file .
Concepts部分告訴了咱們Webpack的定義、目的以及核心概念:
核心概念:
入口(entry): 告訴 Webpack 從那個模塊(文件)開始構建dependency graph. Webpack將會以此爲起點,找到全部的依賴並打包最終造成bundle.
webpack.config.js
中配置entry,Webpack將會默認使用路徑 ./src/index.js
做爲起點開始構建打包.輸出(ouput): 告訴Webpack打包結果的建立位置&命名方式.
webpack.config.js
中配置output,Webpack將會默認在路徑 ./dist
文件夾下建立打包結果main.js
.加載器(loader): loader的做用是將全部類型的文件轉換爲能夠被 dependency graph 直接應用的文件,也就是Webpack封面圖--將全部依賴模塊打包成靜態資源
webpack.config.js
的 module.rules
中進行手動配置,聲明但願進行轉換的文件類型及其對應的處理器loader(test、use).插件(plugin): 執行範圍更廣的任務,例如:優化打包、壓縮、注入新的環境變量等等.
webpack.config.js
的頂部用require
進行聲明,接着在module.plugins
中初始化並根據plugin的文檔進行配置.none
、development
、 production
模式可供選擇. 如今暫時無論這個屬性的配置.Webpack提供了方便開箱即用的默認配置,可是想要充分發揮Webpack的能力,仍是須要使用配置文件.
若是 webpack.config.js
存在,則 webpack
命令將默認選擇使用它,因而咱們在項目根目錄添加文件 webpack.config.js
,項目的文件結構大體以下所示:
webpack-stepbystep └─ dist └─ main.js └─ node_modules └─ src └─ index.js └─ index.html └─ package-lock.json └─ package.json └─ webpack.config.js
爲 webpack.config.js
添加配置,使之實現默認Webpack配置的效果:
const path = require('path'); module.exports = { entry: './src/index.js', output: { filename: 'main.js', path: path.resolve(__dirname, 'dist') } };
刪除dist
文件夾,保存 webpack.config.js
,並打開終端在當前項目下運行 webpack
,運行成功以後發現當前項目目錄再次生成了 dist
文件夾,裏面有 main.js
, 至此咱們成功使用 webpack.config.js
成功復刻了默認Webpack配置的效果~
固然此次實戰的目標確定不止如此,第一次實戰中遺留着一個問題,就是Webpack的默認配置沒法幫助咱們將 index.html
一塊兒打包到 dist
中,這致使項目沒法全自動打包. 如今就來嘗試藉助 webpack.config.js
來解放Webpack的能力,實現項目的全自動化打包.
實現過程分爲兩個步驟:
第一步、每次打包以前清除 dist
內容。已有打包內容容易對新打包內容形成影響,因此在這裏使用一個叫作 clean-webpack-plugin
的插件,這個插件將幫助咱們在每次打包以前清理 dist
文件夾的內容,插件的配置方法以下:
插件安裝:首先經過 npm
再項目中安裝插件:
npm i -D clean-webpack-plugin
配置文件修改:在 webpack.config.js
文件開頭用require引用插件,再在 plugins
數組中添加其插件的實現,完整配置文件代碼以下所示:
const path = require('path'); const CleanWebpackPlugin = require('clean-webpack-plugin'); module.exports = { entry: './src/index.js', output: { filename: 'main.js', path: path.resolve(__dirname, 'dist') }, plugins: [ new CleanWebpackPlugin(['dist']) ] };
index.html
文件到 dist
中,再回到終端運行webpack
, 執行成功後發現 dist
下只有一個剛被建立的 main.js
, 即每次打包以前插件都會自動清理打包目標文件夾~第二步、在Webpack打包過程當中,將根目錄下的 index.html
文件複製到 dist
中. 這裏須要用到一個叫作 html-webpack-plugin
的插件,這個插件功能不少,可是咱們暫時須要它幫咱們將根目錄的 index.html
複製到 dist
中,配置方法以下:
插件安裝:
npm i -D html-webpack-plugin
配置文件修改:在 webpack.config.js
文件開頭用require引用插件,再在 plugins
數組中添加其插件的實現,完整配置文件代碼以下所示:
const path = require('path'); const CleanWebpackPlugin = require('clean-webpack-plugin'); const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { entry: './src/index.js', output: { filename: 'main.js', path: path.resolve(__dirname, 'dist') }, plugins: [ new CleanWebpackPlugin(['dist']), new HtmlWebpackPlugin({ inject: false, template: 'index.html', filename: 'index.html' }) ] };
webpack
, 執行完成後發現 dist
下已經出現了咱們想要的兩個文件 index.html
& main.js
,瀏覽器打開 index.html
, 再次看到熟悉的 Hello Webpack!成功~至此第二次Webpack實戰練習也成功結束了~此次咱們完成了使用一句 webpack
就完成了項目打包,無需粗暴的複製黏貼,真正作到了全自動化打包項目!至此項目提交爲 feat(project): combat: project bundle with webpack.config.js .
To be continued...