webpack编译静态多页面应用

在很久之前,整理过一套webpack2+react的脚手架,主要是为了写单页应用而准备的,地址:https://github.com/owenliang/react-webpack2

最近在公司搬砖,主要是用PHP来做PC和WAP站,会和前端FE同学进行交互。在工作模式上,FE同学会提供一个静态页给PHP,然后PHP同学将数据填充到静态页中,渲染后吐给客户端。

可以这么说,如果你需要做SEO,那么服务端渲染是必然的选择。通过观察FE的静态页,我发现他们是用webpack编译的,所以引发了我动手的一个冲动,决定自己配置一个编译静态多页应用的webpack脚手架出来,地址:

https://github.com/owenliang/webpack-static-html

编译单页和静态多页应用的差别

单页应用一般是基于JSX实现的,JS生成HTML,而webpack本身的实现原理也是基于JS进行依赖分析编译的,两者结合的特别好。

多页应用也可以在每个页面分别使用JSX,其实和单页应用没有太大差别,仍旧是JS为王。而我要说的并不是单纯的多页应用,而是静态多页,也就是通过.html文件编写HTML结构,利用JS实现动态交互。

刚开始的时候我也不太适应,因为以前webpack+react情况下,通过JS(+JSX)实现了所有功能,并且所有文件都可以视作模块,包括图片,样式,皆可直接引用。

而传统静态HTML页面是写在.html文件中的,只有需要Jquery动态处理的逻辑才会写在JS中,这种情况下webpack实际只能编译JS那部分内容,这是一个主要的差别。

解决思路

既然页面是.html中编写的静态内容,那么webpack能做的编译动态逻辑那部分JS(就是我们以往写的jquery DOM增删改查)。

这个过程可以总结为:webpack从某个JS文件开始编译,我们仍旧可以在JS中引入CSS(webpack中一切皆为模块),当webpack分析完成后会编译所有的JS和CSS生成文件,最终在.html中引入这些文件。

大家可以回想一下传统开发模式,先开发HTML静态结构+CSS,然后编写JS文件利用Jquery操作DOM,把JS文件引入到HTML头部,基本是类似的过程。

差别在于,webpack要求我们按照模块化、工程化的方法开发JS,而以往我们可能在一个很大的JS文件中从头写到尾,过上一阵自己都不想看。

实践关键

webpack的编译入口必须是JS文件,所以需要为每个页面开发一个入口JS文件,以这个JS文件开始引入的所有资源(JS、CSS)都将视为同一个单元,最后被引入到对应的页面中即可。

就如同之前所说,一旦你决定使用webpack,那么就要遵循nodeJS的模块化开发。

在传统开发模式中,我们在HTML中依次引入多个JS文件;而在webpack之下,我们将不同功能的方法放到不同的JS文件中,并在入口JS文件中只引入需要用到的方法,这些方法来自于其他JS文件。

webpack工程化带来了很多好处,很重要的一点就是webpack最终编译产物只会包含我们用到的JS模块,而没有引入过的则不会包含。

另外一点是CSS的使用,传统开发模式我们直接在HTML中引入CSS文件;webpack倡导一切皆模块,所以css作为一个模块被引入到JS中,就相当于引入到了HTML页面。请放心,webpack编译JS的过程中会分析引入的CSS,最终生成压缩合并后的CSS文件,并帮我们在HTML中引入它们,所以我们不需要自己在HTML中显式的引入什么CSS。

最后一个特别之处是<img>的处理,在单页应用中我们把本地磁盘上的图片当做模块引入到JS中,并插入到JSX中,所以webpack会追溯出来这些图片资源并进行编译和URL替换。现在我们在静态HTML中引入磁盘上的图片文件,webpack只编译JS所以无法对HTML中的图片进行处理。

解决这个问题需要安装一个html-loader加载器,并在页面对应的JS入口文件中,主动引入一下页面html自身。这个加载器一旦被调用,就会分析html页面中的<img>标签,提取出其中的图片路径交给webpack处理,而webpack将图片视为模块,所以会调用对应的插件(url-loader,file-loader)对图片进行编译,编译后html-loader会将编译后的图片URL替换到html对应位置。

亲自观察

理论结合实践,现在打开项目:https://github.com/owenliang/webpack-static-html,仔细观察webpack配置、目录结构。

src目录是开发阶段的工程目录,通过执行npm run release后会编译项目到dist目录。

整个站点由index和about两个页面组成,公共引用的css、js都被提取到了common文件中,并且每个文件都hash编码,这就是一般传统PC/WAP站点需要的样子。

一般来说,可能还会为webpack配置cdn地址,这样在html中引用的URL就会替换为cdn域名,我们后续需要做的是把编译产物上传到CDN上,仅此而已。

现在,把编译后的HTML交给PHP同学,让他们嵌套数据即可。

发表评论

电子邮件地址不会被公开。