本文首发于 Array_Huang的技术博客——实用至上
,非经做者赞成,请勿转载。
原文地址: http://www.javashuo.com/article/p-bacjobzd-kg.html
若是您对本系列文章感兴趣,欢迎关注订阅这里:https://segmentfault.com/blog/array_huang
按照咱们前面的十一篇的内容来看,本身写一个HTML页面,而后在上面加载webpack打包的js或其它类型的资源,感受不也用得好好的么?javascript
是的没错,不用webpack用requireJs其实也能够啊,甚至于,传统那种人工管理模块依赖的作法也没有什么问题嘛。css
但既然你都已经看到这一篇了,想必早已和我同样,追求着如下这几点吧:html
那么,废话很少说,下面就来讲说使用webpack生成HTML页面有哪些好处吧。前端
在实际项目的开发过程当中,咱们会发现,虽然一个项目里会有不少个页面,但这些页面总有那么几个部分是相同或类似的,尤为是页头页尾,基本上是彻底一致的。那咱们要怎么处理这些共有的部分呢?java
不就是复制粘贴的事嘛?写好一份完整的HTML页面,作下个页面的时候,直接copy一份文件,而后直接在copy的文件上进行修改不就行了吗?
谁是这么想这么作的,放学留下来,我保证不打死你!我曾经接受过这么一套系统,顶部栏菜单想加点东西,就要每一个页面都改一遍,可维护性烂到爆啊。webpack
Iframe流常见于管理后台类项目,可维护性OK,就是缺陷比较多,好比说:git
最近这几年,随着移动互联网的兴起,SPA也变得很是常见了。不过SPA的局限性也很是大,好比搜索引擎没法收录,但我我的最在乎的,是它太复杂了,尤为是一些原本业务逻辑就多的系统,很容易懵圈。程序员
这倒真是一个办法,只是,须要后端的配合,利用后端代码把页面的各个部分给拼合在一块儿,因此这方法对前端起家的程序员仍是有点门槛的。github
所谓“用webpack生成HTML页面”,其实也并非webpack起的核心做用,实际上靠的仍是前端的模板引擎将页面的各个部分给拼合在一块儿来达到公共区域的复用。webpack更多的是组织统筹整个生成HTML页面的过程,并提供更大的控制力。最终,webpack生成的究竟是完整的页面,仍是供后端渲染的模板,就全看你本身把控了,很是灵活,外人甚至察觉不出来这究竟是你本身写的仍是代码统一辈子成的。web
若是你想用在文件名上加hash的方法做为缓存方案的话,那么用webpack生成HTML页面就成为你惟一的选择了,由于随着文件的变更,它的hash也会变化,那么整个文件名都会改变,你总不能在每次编译后都手动修改加载路径吧?仍是放心交给webpack吧。
若是你使用webpack来生成HTML页面,那么,你能够配置好每一个页面加载的chunk(webpack打包后生成的js文件),生成出来的页面会自动用<script>
来加载这些chunk,路径什么的你都不用管了哈(固然前提是你配置好了output.publicPath)。另外,用extract-text-webpack-plugin
打包好的css文件,webpack也会帮你自动添加到<link>
里,至关方便。
使用webpack生成出来的HTML页面能够很安心地跟webpack打包好的其它资源放到一块儿,相对于另起一个目录专门存放HTML页面文件来讲,整个文件目录结构更加合理:
build - index - index - entry.js - page.html - login - entry.js - page.html - styles.css
webpack生成HTML页面主要是经过html-webpack-plugin
来实现的,下面来介绍如何实现。
html-webpack-plugin
的配置项每个html-webpack-plugin的对象实例都只针对/生成一个页面,所以,咱们作多页应用的话,就要配置多个html-webpack-plugin的对象实例:
pageArr.forEach((page) => { const htmlPlugin = new HtmlWebpackPlugin({ filename: `${page}/page.html`, template: path.resolve(dirVars.pagesDir, `./${page}/html.js`), chunks: [page, 'commons'], hash: true, // 为静态资源生成hash值 minify: true, xhtml: true, }); configPlugins.push(htmlPlugin); });
pageArr
其实是各个chunk的name,因为我在output.filename设置的是'[name]/entry.js'
,所以也起到构建文件目录结构的效果(具体请看这里),附上pageArr
的定义:
module.exports = [ 'index/login', 'index/index', 'alert/index', 'user/edit-password', 'user/modify-info', ];
html-webpack-plugin
的配置项真很多,这里仅列出多页应用经常使用到的配置:
/
来控制文件目录结构的,其最终生成的路径,是基于webpack配置中的output.path的。html-webpack-plugin
默认支持ejs格式的模板文件,若是你想使用其它格式的模板文件,那么须要在webpack配置里设置好相应的loader,好比handlebars-loader
啊html-loader
啊之类的。若是不指定这个参数,html-webpack-plugin
会使用一份默认的ejs模板进行渲染。若是你作的是简单的SPA应用,那么这个参数不指定也行,但对于多页应用来讲,咱们就依赖模板引擎给咱们拼装页面了,因此这个参数很是重要。<script>
插入到哪里,默认是插到<body>
的末端,若是设置为'head',则把<script>
插入到<head>
里。html-webpack-plugin
负责加载的js/css文件的网址末尾加个URL参数,此URL参数的值是表明本次编译的一个hash值,每次编译后该hash值都会变化,属于缓存解决方案。html-webpack-plugin
负责加载的chunk文件(打包后生成的js文件),不指定的话就会加载全部的chunk。下面提供一份供生成简单页面(之因此说简单,是由于不指定页面模板,仅用默认模板)的配置:
var HtmlWebpackPlugin = require('html-webpack-plugin'); var webpackConfig = { entry: 'index.js', output: { path: 'dist', filename: 'index_bundle.js' }, plugins: [new HtmlWebpackPlugin({ title: '简单页面', filename: 'index.html', })], };
使用这份配置编译后,会在dist目录下生成一个index.html,内容以下所示:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>简单页面</title> </head> <body> <script src="index_bundle.js"></script> </body> </html>
因为没有指定模板文件,所以生成出来的HTML文件仅有最基本的HTML结构,并不带实质内容。能够看出,这更适合React这种把HTML藏js里的方案。
接下来,咱们演示如何经过制定模板文件来生成HTML的内容,因为html-webpack-plugin
原生支持ejs模板,所以这里也以ejs做为演示对象:
<!DOCTYPE html> <html> <head> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta http-equiv="Content-type" content="text/html; charset=utf-8"/> <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1" /> <title><%= htmlWebpackPlugin.options.title %></title> </head> <body> <h1>这是一个用<b>html-webpack-plugin</b>生成的HTML页面</h1> <p>你们仔细瞧好了</p> </body> </html>
'html-webpack-plugin'的配置里也要指定template参数:
var HtmlWebpackPlugin = require('html-webpack-plugin'); var webpackConfig = { entry: 'index.js', output: { path: 'dist', filename: 'index_bundle.js' }, plugins: [new HtmlWebpackPlugin({ title: '按照ejs模板生成出来的页面', filename: 'index.html', template: 'index.ejs', })], };
那么,最后生成出来的HTML文件会是这样的:
<!DOCTYPE html> <html> <head> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta http-equiv="Content-type" content="text/html; charset=utf-8"/> <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1" /> <title>按照ejs模板生成出来的页面</title> </head> <body> <h1>这是一个用<b>html-webpack-plugin</b>生成的HTML页面</h1> <p>你们仔细瞧好了</p> <script src="index_bundle.js"></script> </body> </html>
到这里,咱们已经能够控制整个HTML文件的内容了,那么生成后端渲染所需的模板也就不是什么难事了,以PHP的模板引擎smarty为例:
<!DOCTYPE html> <html> <head> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta http-equiv="Content-type" content="text/html; charset=utf-8"/> <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1" /> <title><%= htmlWebpackPlugin.options.title %></title> </head> <body> <h1>这是一个用<b>html-webpack-plugin</b>生成的HTML页面</h1> <p>你们仔细瞧好了</p> <p>这是用smarty生成的内容:<b>{$articleContent}</b></p> </body> </html>
接下来在上面例子的基础上,咱们演示如何处理资源的动态路径:
var HtmlWebpackPlugin = require('html-webpack-plugin'); var webpackConfig = { entry: 'index.js', output: { path: 'dist', filename: 'index_bundle.[chunkhash].js' }, plugins: [new HtmlWebpackPlugin({ title: '按照ejs模板生成出来的页面', filename: 'index.html', template: 'index.ejs', })], module: { loaders: { // 图片加载器,雷同file-loader,更适合图片,能够将较小的图片转成base64,减小http请求 // 以下配置,将小于8192byte的图片转成base64码 test: /\.(png|jpg|gif)$/, loader: 'url?limit=8192&name=./static/img/[hash].[ext]', }, }, };
<!DOCTYPE html> <html> <head> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta http-equiv="Content-type" content="text/html; charset=utf-8"/> <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1" /> <title><%= htmlWebpackPlugin.options.title %></title> </head> <body> <h1>这是一个用<b>html-webpack-plugin</b>生成的HTML页面</h1> <p>你们仔细瞧好了</p> <img src="<%= require('./imgs/login-bg.jpg') %>" /> </body> </html>
咱们改动了什么呢?
output.filename
里,咱们添了个变量[chunkhash],这个变量的值会随chunk内容的变化而变化,那么,这个chunk文件最终的路径就会是一个动态路径了。<img>
,它的src是require一张图片,相应地,咱们配置了针对图片的loader配置,若是图片比较小,require()
就会返回DataUrl,而若是图片比较大,则会拷贝到dist/static/img/
目录下,并返回新图片的路径。下面来看看,到底html-webpack-plugin
能不能处理好这些动态的路径。
<!DOCTYPE html> <html> <head> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta http-equiv="Content-type" content="text/html; charset=utf-8"/> <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1" /> <title>按照ejs模板生成出来的页面</title> </head> <body> <h1>这是一个用<b>html-webpack-plugin</b>生成的HTML页面</h1> <p>你们仔细瞧好了</p> <img src="data:image/jpeg;base64,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" /> <script src="index_bundle.c3a064486c8318e5e11a.js"></script> </body> </html>
显然,html-webpack-plugin
成功地将chunk加载了,又处理好了转化为DataUrl格式的图片,这一切,都是咱们手工难以完成的事情。
至此,咱们实现了使用webpack生成HTML页面并尝到了它所带来的甜头,但咱们还没有实现“对多个页面共有的部分实现复用”,下一篇《webpack多页应用架构系列(十三):构建一个简单的模板布局系统》咱们就来介绍这部分的内容。
诸位看本系列文章,搭配我在Github上的脚手架项目食用更佳哦(笑):Array-Huang/webpack-seed(https://github.com/Array-Huang/webpack-seed
)。
https://segmentfault.com/a/1190000006843916
https://segmentfault.com/a/1190000006863968
https://segmentfault.com/a/1190000006871991
https://segmentfault.com/a/1190000006887523
https://segmentfault.com/a/1190000006897458
https://segmentfault.com/a/1190000006907701
https://segmentfault.com/a/1190000006952432
https://segmentfault.com/a/1190000006992218
https://segmentfault.com/a/1190000007030775
https://segmentfault.com/a/1190000007043716
https://segmentfault.com/a/1190000007104372
https://segmentfault.com/a/1190000007126268
https://segmentfault.com/a/1190000007159115
本文首发于 Array_Huang的技术博客——实用至上
,非经做者赞成,请勿转载。
原文地址: http://www.javashuo.com/article/p-bacjobzd-kg.html
若是您对本系列文章感兴趣,欢迎关注订阅这里:https://segmentfault.com/blog/array_huang