軟件工程的工程化開發概念由來已久,但對於前端開發來講,咱們沒有像VS或者eclipse這樣量身打造的IDE,由於在大多數人眼中,前端代碼無需編譯,所以只要一個瀏覽器來運行調試就好了。可是時至今日,互聯網特別是移動互聯網爲前端開發帶來了更大的機會,同時前端代碼也變得愈來愈複雜,愈來愈難以管理,所以前端工程化開發的工做能夠說是刻不容緩。css
那麼前端工程化開發到底須要解決哪些前端工程師們迫不及待的問題呢?我的認爲至少包含如下幾點:html
1. 專業的IDE支持,完成包括項目初始化,語法提示,項目編譯,打包等工做。前端
2. 良好的模塊化代碼管理結構,模塊化可使咱們編寫的組件或者代碼達到高度複用,下降代碼間的耦合性;同時能夠良好的與第三方組件兼容。node
3. 簡單易配置的前端測試環境,完成組件的單元測試,頁面的集成測試;同時提供良好的DEBUG環境,能夠很好的定位錯誤的所在以及錯誤的詳細信息。jquery
4. 靜態資源(圖片/字體/CSS/JS等)的良好管理方案,一是靜態的文件版本問題,二是對於小圖標自動轉BASE64,減小HTTP請求webpack
5. 完整的代碼版本管理,打包,發佈,多環境部署,測試反饋等運維支持git
固然,以上只是我的意見。每一個公司、每一個項目的狀況不同,所須要的條件都會有所不一樣。github
以上這些需求,在之前基本上都是不敢想象的,這些工具都須要訪問文件系統或者網絡,不多有比較完整的解決方案。(好了,早期也有相似於Ant這樣的Java解決方法,對前端開發人員要求太高並且不是很好用)好在,偉大的NodeJs誕生了,因而乎,基於NodeJs出現了不少優秀框架,像Grunt和 Gulp等。web
好了,今天的主題是webpack!讓咱們來看下webpack做爲後起之秀,是如何對前端工程化進行支持的!npm
你們注意,這裏所說的動態生成HTML,是指咱們使用webpack來動態產生咱們最終所指望的HTML文件,而不是指在瀏覽器運行時使用JS生成HTML片斷。
那爲何要動態生成HTML,我本身寫不行嗎?答案固然是能夠的。
之因此要動態生成,主要是但願webpack在完成前端資源打包之後,自動將打包後的資源路徑和版本號寫入HTML中,達到自動化的效果。
你們能夠回想一下咱們以前的三篇文章中介紹的案例,在那個練手的項目中,咱們頁面上的script標籤是咱們本身寫的,那麼若是咱們須要給JS添加上版本號的話,豈不是每次都的去修改?還有CSS,都是內嵌在JS中的,待JS加載後再建立style標籤,而後寫入css內容。這麼作的話,瀏覽器須要先等待JS加載完成後,才能生成CSS樣式,頁面上會有一個等待過程,這個過程頁面是徹底沒有樣式的。這固然不是咱們所想要的。
咱們的目標是:webpack根據指定的模板,插入打包編譯後CSS文件路徑;插入打包生成的JS的文件路徑。而且還須要爲兩者添加版本號。另外,咱們還能夠同時將HTML進行壓縮,進一步減小文件大小。
咱們這裏默認你們的開發環境已經安裝了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" }
準備就緒,咱們開始建立項目目錄:
- 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)
最後是咱們的重頭戲,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也會被提取出來嗎?下一章咱們將繼續探索這個問題。