-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
简单实用的webpack-html-include-loader(附开发详解) #13
Labels
Comments
这段代码有点问题,会将代码注入到页面中,而不是渲染页面,需要改成下面这段代码
|
最上面的那段是ejs里的语法,用的是 |
plugins: [new HtmlWebpackPlugin({
template: 'src/index.ejs',
inject: true,
minify: {
collapseWhitespace: true
}
}), 我这边是直接使用的是 HtmlWebpackPlugin ,没有使用 ejs-loader,<%= 就会输出代码, 而 <%- 则能正常渲染 看官网解释是 <%= 是会转义的,而 <%- 是非转义的 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
背景介绍
在单页应用盛行的今天,很多人似乎已经把简单的切图不当做一种技术活了。对于切页面,写静态网站都快要嗤之以鼻了。其实并非如此,写静态页面是前端入门的基本工作,是基本功扎实的体现。而且在工作中,我们也少不了要开发一些静态的官网类网站。我们要做的是想一想如何更好的开发静态页面。
歪马最近因工作原因,需要对一个托管于内容管理系统的官网类网站进行迁移。既然要重新弄,那工程化自然少不了,webpack、css 预编译等全上了。这样才能向更好的开发体验靠齐。
由于是静态官网,在使用 webpack 的时候,需要指定多入口,并且为不同的入口指定不同的 template 模板。借助
html-webpack-plugin
可以为不同的入口指定模板,如下所示:通过对入口列表进行遍历,我们可以为不同的入口指定不同的模板。
在使用 Vue/React 等框架时,我们早已习惯在开发的过程中进行组件的抽取与复用。那么在这类纯静态的网站开发中,我们也一定想要尽可能的复用页面内的公共部分,如 header、footer、copyright 等内容。
这些在服务端渲染的开发模式下早就已经很成熟了,借助模板引擎可以轻松地完成,如
nunjucks
/pug
/ejs
等。webpack-html-plugin
中的template
默认使用的就是ejs
。既然官方使用的就是ejs
,那么我们也先从这个方向找找方案。经过歪马的尝试,发现
ejs
并不能很好的实现以下功能:支持 include,但是传参的格式不够优雅,用法如下:
index.ejs:
header.ejs:
不支持对文件内的图片 src 进行处理
无法对图片进行处理,这就没得玩了。歪马只能另寻他法,最后找到的方案都不理想。就自己动手实现了一个功能简单,方便易用的 HTML 包含 loader —— webpack-html-include-loader。
webpack-html-include-loader 包含以下核心功能:
本文依次介绍这 4 个核心功能,并讲解相关实现。读完本文,你会收获如何使用这一 loader,并且获悉一点 webpack loader 的开发经验,如有问题还请不吝赐教。
一、实现基础的包含功能
为了能够更灵活的组织静态页面,我们必不可少的功能就是 include 包含功能。我们先来看看如何实现包含功能。
假设,默认情况下,我们使用以下语法标记进行 include:
想要实现这一功能,其实比较简单。webpack 的 loader 接受的参数可以是原始模块的内容或者上一个 loader 处理后的结果,这里我们的 loader 直接对原始模块的内容进行处理,也就是内容字符串。
所以,想要实现包含功能,只需要通过正则匹配到包含语法,然后全局替换为对应的文件内容即可。整体代码如下
其中,
const pathRelative = this.context
,是 webpack loader API提供的,context
表示当前文件的所在目录。借助这一属性,我们能够获取被包含文件的具体路径,进而获取文件内容进行替换。此外,你可能还注意到了代码中还调用了
this.addDependency(filePath)
,这一方法可以将文件添加到了依赖中,这样就可以监听到文件的变化了。其余逻辑比较简单,如果你对字符串
replace
不是很熟悉,推荐看下阮一峰老师的这篇正则相关的基础文档。好了,到现在我们实现了最基础的 HTML 包含功能。但是,我们显然不满足于此,最起来嵌套包含还是要支持的吧?下面我们一起来看看如何实现嵌套包含。
二、提高包含的灵活度:嵌套包含
上面,我们已经实现了基础的包含功能,再去实现嵌套包含其实就很简单了。递归地处理一下就好了。由于要递归调用,所以我们将 include 语法标记的替换逻辑提取为一个函数
replaceIncludeRecursive
。下面上代码:
逻辑很简单,把原本的替换逻辑放到了
replaceIncludeRecursive
函数内,在主逻辑中调用更该方法即可。另外,webpack-html-include-loader
默认设置了最大嵌套层数的限制为5
层,超过则不再替换。至此,我们实现了比较灵活的 include 包含功能,不知道你还记不记得最开始
ejs
的包含是支持传入参数的,可以替换包含模板中的一些内容。我们可以称之为变量。三、传入参数 & 变量解析
同样,先设定一个默认的传入参数的语法标记,如下:
<%- include("./header/main.html", {"title": "首页"}) %>
。在包含文件时,通过 JSON 序列化串的格式传入参数。
然后在被包含的文件中使用
<%= title %>
进行变量插入。那么想要实现变量解析,我们需要先实现传入参数的解析,然后再替换到对应的变量标记中。
代码如下:
其中,当 loader 处理过程中遇到错误时,可以借助 oader API 的
emitError
来对外输出错误信息。至此,我们实现了 webpack-html-include-loader 所应该具备的所有主要功能。为了让使用者更加得心应手,我们再扩展实现一下自定义语法标记的功能。
四、自定义语法标记
通过指定 loader 的
options
,或者内嵌query
的形式,我们可以传入自定义选项。本文是从webpack-html-plugin
说起,我们就以此为例。我们将文章开头的 webpack-html-plugin 相关的代码做如下修改,将 include 的起始标记改为<#-
:想要实现自定义的语法标记也很简单,将自定义的标记动态传入正则即可。只有一点需要注意,那就是要对传入的值进行转义。
正则表达式中,需要反斜杠转义的,一共有 12 个字符:
^
、.
、[
、$
、(
、)
、|
、*
、+
、?
、{
和\\
。如果使用 RegExp 方法生成正则对象,转义需要使用两个斜杠,因为字符串内部会先转义一次。代码逻辑如下:
escapeForRegExp
的逻辑如下,其中$&
为正则匹配的字符串:其中,
getOptions
方法是loader-utils提供的方法,它额外还提供了了很多工具,在进行 loader 开发时很有用武之地。五、其他一些逻辑
除了上面的核心功能,还有比较细的逻辑,比如借助schema-utils对自定义选项进行验证,自定义的一些通用函数,这里就不一一介绍了。感兴趣的同学可以在翻看翻看源码。链接如下:https://github.com/verymuch/webpack-html-include-loader,欢迎批评指正 + star。
总结
本文介绍了
webpack-html-include-loader
的主要功能以及开发思路,希望读完本文你能够有所收获,对于 webpack loader 的开发有一个简单的了解。The text was updated successfully, but these errors were encountered: