上一章咱们使用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...