Hello,大家好!在前面三章中我們與大家分享如何使用webpack來完成前端的模組化打包工作,並附帶了一些簡單的案例實現,算是webpack的一個入門吧。
從這一章開始,我們將陸續為大家介紹如何使用webpack來完成前端工程化開發。
1.什麼是工程化開發
軟體工程的工程化開發概念由來已久,但對於前端開發來說,我們沒有像VS或者eclipse這樣量身打造的IDE,因為在大多數人眼中,前端程式碼無需編譯,因此只要一個瀏覽器來執行除錯就行了。但是時至今日,網際網路特別是移動網際網路為前端開發帶來了更大的機會,同時前端程式碼也變得越來越複雜,越來越難以管理,因此前端工程化開發的工作可以說是刻不容緩。
那麼前端工程化開發到底需要解決哪些前端工程師們火燒眉毛的問題呢?個人認為至少包含以下幾點:
1. 專業的IDE支援,完成包括專案初始化,語法提示,專案編譯,打包等工作。
2. 良好的模組化程式碼管理結構,模組化可以使我們編寫的元件或者程式碼達到高度複用,降低程式碼間的耦合性;同時可以良好的與第三方元件相容。
3. 簡單易配置的前端測試環境,完成元件的單元測試,頁面的整合測試;同時提供良好的DEBUG環境,可以很好的定位錯誤的所在以及錯誤的詳細資訊。
4. 靜態資源(圖片/字型/CSS/JS等)的良好管理方案,一是靜態的檔案版本問題,二是對於小圖示自動轉BASE64,減少HTTP請求
5. 完整的程式碼版本管理,打包,釋出,多環境部署,測試反饋等運維支援
當然,以上只是個人意見。每個公司、每個專案的情況不一樣,所需要的條件都會有所不同。
以上這些需求,在以前基本上都是不敢想象的,這些工具都需要訪問檔案系統或者網路,很少有比較完整的解決方案。(好了,早期也有類似於Ant這樣的Java解決方法,對前端開發人員要求過高而且不是很好用)好在,偉大的NodeJs誕生了,於是乎,基於NodeJs出現了很多優秀框架,像Grunt和 Gulp等。
好了,今天的主題是webpack!讓我們來看下webpack作為後起之秀,是如何對前端工程化進行支援的!
2. 動態生成HTML
大家注意,這裡所說的動態生成HTML,是指我們使用webpack來動態產生我們最終所期望的HTML檔案,而不是指在瀏覽器執行時使用JS生成HTML片段。
那為什麼要動態生成HTML,我自己寫不行嗎?答案當然是可以的。
之所以要動態生成,主要是希望webpack在完成前端資源打包以後,自動將打包後的資源路徑和版本號寫入HTML中,達到自動化的效果。
大家可以回想一下我們之前的三篇文章中介紹的案例,在那個練手的專案中,我們頁面上的script標籤是我們自己寫的,那麼如果我們需要給JS新增上版本號的話,豈不是每次都的去修改?還有CSS,都是內嵌在JS中的,待JS載入後再建立style標籤,然後寫入css內容。這麼做的話,瀏覽器需要先等待JS載入完成後,才能生成CSS樣式,頁面上會有一個等待過程,這個過程頁面是完全沒有樣式的。這當然不是我們所想要的。
我們的目標是:webpack根據指定的模板,插入打包編譯後CSS檔案路徑;插入打包生成的JS的檔案路徑。並且還需要為二者新增版本號。另外,我們還可以同時將HTML進行壓縮,進一步減少檔案大小。
3.初始化專案、安裝依賴
我們這裡預設大家的開發環境已經安裝了npm以及webpack,尚未安裝的同學可以自行安裝。
A.新建一個空專案,然後通過 npm init 對專案進行初始化,按照提示輸入專案的基本資訊,然後生成package.json檔案。這個檔案裡面會儲存我們即將安裝的一些npm外掛資訊,便於二次移植開發。
B.安裝專案所需依賴:
npm install css-loader jquery@1 style-loader html-webpack-plugin --save-dev
npm install extract-text-webpack-plugin --save-dev
依次為css載入器,jquery,style載入器,HTML生成外掛以及檔案提取外掛。
最終package.json的依賴宣告得到更新:
"devDependencies": { "css-loader": "^0.23.0", "extract-text-webpack-plugin": "^0.9.1", "html-webpack-plugin": "^1.7.0", "jquery": "^1.11.3", "style-loader": "^0.13.0", "webpack": "^1.12.9", "webpack-dev-server": "^1.14.0" }
4. 建立目錄,新增測試檔案
準備就緒,我們開始建立專案目錄:
- webapp - src #程式碼開發目錄 - css #css目錄,按照頁面(模組)、通用、第三方三個級別進行組織 + page + common + lib + img #圖片資源 - js #JS指令碼,按照page、components進行組織 + page + view #HTML模板 - dist #webpack編譯打包輸出目錄,同樣按照css/js/img進行組織 + css + js + view + node_modules #所使用的nodejs模組 package.json #專案配置 webpack.config.js #webpack配置 README.md #專案說明
dist目錄也可以不建立任何子目錄,這裡為了方便檢視,將js/css/html分開存放。
然後我們在src目錄建立幾個測試檔案,詳細的程式碼大家可以前往 https://github.com/xiaoyunchen/webpack/tree/master/src 檢視原始碼。
我們先來看下index.js的內容:
1 //引入CSS 2 require("../../css/lib/reset.css"); 3 require("../../css/common/global.css"); 4 require("../../css/page/index.css"); 5 6 document.write('Hello Index Js');
程式碼很簡單,主要是引入了幾個css檔案。再看下我們的 /view/index.html 這個模板的內容
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Index主頁</title> <meta name="author" content="https://github.com/xiaoyunchen/webpack"/> <meta name="date" content="2015-12-3"/> <meta name="description" content="基於webpack的前端工程化開發解決方案探索"/> <!-- 作者:https://github.com/xiaoyunchen/webpack 時間:2015-12-03 描述:head中無需再引入css以及facicon,webpack將根據入口JS檔案的要求自動實現按需載入或者生成style標籤 --> </head> <body> <p>Hello,Webpack!!</p> <!-- 作者:chyun532@qq.com 時間:https://github.com/xiaoyunchen/webpack 描述:body中同樣無需單獨引入JS檔案,webpack會根據入口JS檔案自動實現按需載入或者生成script標籤,還可以生成對應的hash值 --> </body> </html>
這是一個簡單的HTML模板,值得一提的是我們在這裡並沒有引入任何的CSS和JS,我們希望通過webpack打包來自動生成。(這裡的模板還支援 Blueimp)
5. webpack配置
最後是我們的重頭戲,webpack.config.js,我們將在這裡配置一些webpack任務,來完成我們的需求:
1 var path=require('path'); 2 var webpack = require('webpack'); 3 var ExtractTextPlugin = require("extract-text-webpack-plugin"); 4 var HtmlWebpackPlugin = require('html-webpack-plugin'); 5 module.exports={ 6 entry:{ 7 index:"./src/js/page/index.js", 8 }, 9 output:{ 10 path: path.join(__dirname,'dist'), 11 publicPath: "/webpack/dist/", 12 filename: "js/[name].js", 13 chunkFilename: "js/[id].chunk.js" 14 }, 15 module: { 16 loaders: [ //載入器 17 {test: /\.css$/, loader:ExtractTextPlugin.extract("style", "css") } 18 ] 19 }, 20 plugins:[ 21 new ExtractTextPlugin("css/[name].css"), //單獨使用style標籤載入css並設定其路徑 22 new HtmlWebpackPlugin({ //根據模板插入css/js等生成最終HTML 23 favicon:'./src/img/favicon.ico', //favicon路徑 24 filename:'/view/index.html', //生成的html存放路徑,相對於 path 25 template:'./src/view/index.html', //html模板路徑 26 inject:true, //允許外掛修改哪些內容,包括head與body 27 hash:true, //為靜態資源生成hash值 28 minify:{ //壓縮HTML檔案 29 removeComments:true, //移除HTML中的註釋 30 collapseWhitespace:false //刪除空白符與換行符 31 } 32 }) 33 ] 34 };
這個配置檔案再之前的文章中我們已經講過很多次了,這裡就不在贅述,只對其中幾點比較關鍵的點進行分析:
17行:css載入器,只是這裡改用了檔案提取外掛,將css提取出來單獨作為一個檔案進行儲存。
21行:配置提取出來的css檔名以及存放路徑
22行: html-webpack-plugin 這是webpack中生成HTML的外掛,裡面有詳細的配置說明,大家可以前往檢視。
23行:配置favicon,通過webpack引入同時可以生成hash值
24行:配置最終生成HTML檔案存放路徑
25行:我們所使用的模板
26行:允許webpack修改哪些內容,可選值為head和body,true的話是都可以修改
27行:為靜態資源生成hash值
28行:壓縮最終生成的HTML檔案,相關配置引數請前往 html-minifer 檢視。(這裡為了方便後面檢視,沒有移除HTML中的空白符與換行符。)
OK,下面我們在專案的根目錄下執行 webpack 打包命令完成專案打包:
打包成功後,我們前往/dist/view目錄下檢視生成的index.html是什麼樣
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Index主頁</title> <meta name="author" content="https://github.com/xiaoyunchen/webpack"> <meta name="date" content="2015-12-3"> <meta name="description" content="基於webpack的前端工程化開發解決方案探索"> <link rel="shortcut icon" href="/webpack/dist/favicon.ico?69fed78822d5f8d3895c"><link href="/webpack/dist/css/index.css?69fed78822d5f8d3895c" rel="stylesheet"></head> <body> <p>Hello,Webpack!!</p> <script src="/webpack/dist/js/index.js?69fed78822d5f8d3895c"></script></body> </html>
可以看到生成的檔案除了保留原模板中的內容以外,還根據入口檔案index.js的定義,自動新增需要引入CSS與JS檔案,以及favicon,同時還新增了相應的hash值。
執行這個檔案,可以看到程式碼正常,引入的檔案路徑也都OK!
是的,我們最初想要通過動態生成HTML的目的達到了。
webpack根據指定的模板,插入打包編譯後CSS檔案路徑;
插入打包生成的JS的檔案路徑。並且還需要為二者新增版本號。
另外,我們還可以同時將HTML進行壓縮,進一步減少檔案大小。
今天的分享就到這裡。可能大家還有些疑問:按需載入的JS/CSS也會被提取出來嗎?下一章我們將繼續探索這個問題。