上一章咱們使用webpack對項目進行了工程化改造,實現了從簡單系統到多模塊系統的打包升級,你可能覺得如今就完成了webpack的配置,可是實際上如今項目仍是處於webpack入門級配置的程度。調試一下代碼就會發現,除了比原先項目變得稍微整潔以及完成了app.js模塊引入以外,仍然有不少不足:css
1. 程序被打包到一個文件中,致使調試日誌全都指向了bundle.js文件,沒法追蹤錯誤和警告; 2. 打包以後的dist目錄應包含項目全部功能,如今缺乏index.html; 3. 每次修改完代碼想要運行的時候都須要輸入*npm run build*從新打包項目;
應該明確一點,打包項目是爲了方便咱們的開發調試而不是增長開發複雜度,因此爲了使讓咱們的開發變得更加舒服,這些問題須要立刻解決。html
爲了更容易地追蹤錯誤和警告,應將編譯後的代碼bundle.js映射回原始代碼。打包工具的開發者確定早就考慮到了打包致使的日誌追蹤問題,因此咱們在webpack的文檔中很容易就找到這個:使用source map,也就是使用source-map功能實現編譯後代碼到源代碼的映射。因而在項目的webpack.config.js文件中加入:webpack
devtool: 'inline-source-map',
從新編譯結果以下:
git
咱們發現bundle.js文件變大了,下面的編譯提示也告訴咱們文件過大將影響性能,因此當咱們將代碼打包發佈到生產環境的時候應該關閉掉source-map或者使用其餘配置(劃重點)。source-map除了咱們用到的配置以外還有其餘不一樣選項,若是想要更深刻學習就閱讀這裏:source-map 指南- Devtool。github
修改以後從新運行代碼,日誌打印結果以下:web
ok如今能夠成功映射源代碼輸出日誌了。npm
dist中如今只有bundle.js文件,index.html仍在根目錄,咱們想要成功運行程序,則每次編譯都應清除dist目錄下文件,再把最新的index.html複製到dist中,與bundle.js配合運行。json
首先考慮如何往dist加入html文件,參考文檔設定 HtmlWebpackPlugin,閱讀以後發現大概意思是:在webpack.config.js中加入插件htmlwebpackplugin,而後就能夠自動生成一個全新的index.html。segmentfault
那咱們原來的html咋辦呢,裏面有meta、title、對js和css的引用,還有一些其餘代碼,難道只能拋棄他們嗎?固然是不可能的,htmlwebpackplugin做爲一個插件,是爲讓咱們在編譯打包過程當中得到更好的體驗,特別是自動爲index.html添加生成後文件引用而不用手動修改這一功能。想要更好地使用它就先閱讀一下htmlwebpackplugin的Readme,看完大概知道經過在webpack.config.js配置htmlwebpackplugin,使其在目標目錄生成一個原來index.html類似的html,話有點多如今立刻開始,先安裝html-webpack-plugin:數組
yarn add html-webpack-plugin --save-dev
而後模仿設定 HtmlWebpackPlugin,在webpack.config.js中完成基礎index.html生成配置:
const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { entry: './src/app.js', devtool: 'inline-source-map', plugins: [ new HtmlWebpackPlugin({ title: '口袋妖怪' }) ], output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist') } };
上面配置中咱們作了兩件事:
1. 加入html-webpack-plugin插件的引用; 2. 在plugins數組中建立了HtmlWebpackPlugin的對象(最終webpack將根據該插件對象的配置造成咱們的新index.html);
npm run build一下,如今咱們看看生成的index.html和本來的index.html有什麼不同:
看來還有點差距,咱們還須要對新index.html的<body>插入 ng-controller="AppController",而後再在<body>中加入導航&ngView的html。官方沒說怎麼配置,因此咱們參考了Github-html-webpack-plugin的Readme,在Options中找到一個簡單的配置參數template,並瞭解到咱們只須要建立並引用一個html做爲模板,便可以輕鬆生成想要的index.html,故在根目錄建立index.tpl.html以下:
<!DOCTYPE html> <html lang="en" ng-app="pokemon-app"> <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><%= htmlWebpackPlugin.options.title %></title> </head> <body ng-controller="AppController"> <h1>口袋妖怪管理系統</h1> <div> <h2>快速導航:</h2> <a href="/#!/pokemons">口袋妖怪</a> <a href="/#!/skills">技能</a> <a href="/#!/hagberrys">樹果</a> <a href="/#!/props">道具</a> <a href="/#!/games">遊戲</a> </div> <div ng-view></div> </body> </html>
再修改webpack.config.js中的插件:
plugins: [ new HtmlWebpackPlugin({ title: '口袋妖怪', template: 'index.tpl.html' }) ]
執行編譯npm run build,看到dist/index.html以下:
使用命令行進入dist目錄,開啓http-server,而後打開對應url:
失敗緣由是"沒法加載pm-list.html",這裏暴露了咱們打包過程的一個問題,即當前項目只是打包了全部js,可是對於每一個模塊的html模板文件(list & detail)卻仍然是用相對路徑引用的。正式上線的話只會將dist文件夾放到服務器上,而list & detail是讀不到的,因此咱們須要使用webpack將這兩個html也一塊兒打包進bundle.js中。
這時很明顯的,咱們不能再用相對路徑引用html模板了,應該把list & detail的html看成字符串加載進bundle.js,因而修改pokemon.js以下:
import angular from 'angular'; import ngRoute from 'angular-route'; import pmlist from './pm-list.html'; import pmdetail from './pm-detail.html'; export default angular.module('pokemon-app.pokemon', [ngRoute]) .config(['$routeProvider', function ($routeProvider) { $routeProvider .when('/pokemons', { template: pmlist, controller: 'PMListController' }) .when ('/pokemon/:no', { template: pmdetail, controller: 'PMDetailController' }) }]) .controller('PMListController', PMListController) .controller('PMDetailController', PMDetailController) .name;
上面咱們作了兩件事:
1. 用import引入兩個html模板; 2. 將原來的templateUrl改成template並賦予其引用的html模板文件;
通過修改,模塊html的內容文本應該也會被打包到bundle.js中。完成編輯以後運行npm run build,發現:
如上圖高亮處所示,list文件和detail文件的錯誤都是"解析失敗,須要對應類型的loader"。查閱Loader文檔可知,webpack使用loader來預處理各類文件,那咱們如今須要解析html內容,天然是使用用來加載文件原始內容的raw-loader,參考文檔中的使用方法,先安裝:
yarn add raw-loader --save-dev
再在webpack.config.js的module.exports={}的大括號中加入:
module: { rules: [{ test: /\.html$/, loader: 'raw-loader' }] },
完成以後運行npm run build,發現編譯打包成功,再嘗試運行http-server dist,發現管理系統的口袋妖怪部分已經可以正常使用了!快速將其餘模塊按照pokemon的修改方式進行修改,完成編譯以後,該項目的dist文件應該是可以直接部署在服務器上運行的了,也就是說咱們已經成功實現了項目打包工做的基礎功能了~
完成了上一小結的實踐以後項目的打包上線應該是沒什麼問題了,不過若是項目在上線前出現了重大修改或者回撤,dist目錄下可能殘留有一些冗餘文件。官方文檔說每次編譯打包前先清除dist目錄文件是比較推薦的作法。那麼如今就來考慮下如何每次構建都清除dist中的文件了,參考文檔清理 /dist 文件夾,先安裝clean-webpack-plugin插件:
yarn add clean-webpack-plugin --save-dev
再在webpack.config.js插入引用並建立清空實例:
const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const CleanWebpackPlugin = require('clean-webpack-plugin'); //插入引用 module.exports = { entry: './src/app.js', devtool: 'inline-source-map', plugins: [ new CleanWebpackPlugin(['dist']), //建立清空實例 new HtmlWebpackPlugin({ title: '口袋妖怪', template: 'index.tpl.html' }) ], module: { rules: [{ test: /\.html$/, loader: 'raw-loader' }] }, output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist') } };
如今執行 npm run build,再檢查 /dist 文件夾。若是一切順利,你如今應該不會再看到舊的文件,只有構建後生成的文件!
至此,咱們每次使用npm run build以後都能生成無遺留及冗餘文件的、完成代碼壓縮的index.html 及 bundle.js,也就是能夠直接將dist部署到服務器運行咱們的網站了(記得關閉或修改source-map)。
用過Vue2或者React官方CLI搭建過項目的同窗都知道,這些項目都具備實時重載頁面功能,即修改文件後自動從新加載網頁來展現修改效果。咱們引入webpack構建項目的目的天然也是可以這樣方便地進行開發。爲了解決每次編寫完成代碼後都要從新輸入編譯命令的問題,咱們查閱webpack文檔找到了這個:選擇一個開發工具,對比一下官方提供的三種自動編譯方式:
按照KISS原則,咱們確定選擇一個符合咱們需求的最簡單的東西,因此接下來咱們將使用webpack-dev-server來達到咱們的目的,首先安裝webpack-dev-server插件:
yarn add webpack-dev-server --save-dev
安裝完成以後,在webpack.config.js中加入服務器開啓位置配置:
module.exports = { entry: './src/app.js', devtool: 'inline-source-map', devServer: { // 服務器開啓位置配置 contentBase: './dist' }, ..., ... };
完成配置後,在webpack-dev-server運行過程當中,該文件夾將做爲可訪問文件以供訪問。接下來咱們在package.json文件中加入一行'start'腳本以運行webpack-dev-server:
"scripts": { "start": "webpack-dev-server --open", // 新增 "build": "webpack" }
如今只須要簡單運行npm start,就會看到瀏覽器自動加載頁面。若是咱們修改代碼並保存,頁面將會自動重載。
至此咱們已經完成了項目的實時重載功能。在開發以前運行npm start,等待初始化打包完成以後,每次咱們完成代碼修改並保存,頁面都會自動重載以展現新頁面。
口袋妖怪SPA系統源碼地址:https://github.com/Nodreame/p...
本章基本功能提交:build(webpack): add source-map & auto bulid & finish dist & merge Readme
至此,咱們系統已經基本完成了項目的工程化,項目當前支持自動實時重載、日誌映射,以及支持將編譯打包後的dist文件夾部署到服務器直接運行。既然已經完成開發環境的構建那麼接下來天然要繼續開發項目啦!繼續設計接下來的功能和樣式,讓它越發豐富起來吧!請看下章~
從零開始搭建口袋妖怪管理系統(1)-從Angular1.x開始
從零開始搭建口袋妖怪管理系統(2)-藉助ngRoute實現詳情頁面跳轉
從零開始搭建口袋妖怪管理系統(3)-實現一個簡單的SPA管理系統
從零開始搭建口袋妖怪管理系統(4)-藉助webpack4.6工程化項目(上)
To be continue...