webpack生成html文件,用于后端渲染的研究
来源:互联网 发布:程序员的自我修养 ppt 编辑:程序博客网 时间:2024/06/05 05:30
不适用后端渲染的原因
webpack的打包方式是把所有的资源都打包成bundle.js,并用一个没有内容的html引入生成的bundle.js,不太熟悉的同学可以参看慕课网的视频教程。但是如果公司的建站方式是后端渲染的话(如jsp),那就不能使用webpack了,因为webpack会把html也打包在bundle.js中。本文就是介绍如何用webpack生成我们需要的html,以及其中的问题和优化。
主要思路
webpack的html-webpack-plugin插件,可以设置一个template,我们可以在这个template上做文章,配合上相应的loader,就可以生成我们需要的html。
项目结构
下面是我的webpack目录结构
HTML部分
如何生成我们需要的html文件呢?
html-webpack-plugin的使用
我们采用曲线救国的方式生成我们需要的html,用于后端渲染。这就要使用到html-webpack-plugin的template属性。
module.exports = { entry: 'index.js', output: { path: __dirname + '/dist', filename: 'index_bundle.js' }, plugins: [ new HtmlWebpackPlugin(), // 生成一个空的html,用于引入webpack打包好的js文件 new HtmlWebpackPlugin({ // 再生成一个html filename: 'test.html', template: 'src/assets/test.html' //注意这里可以使用一个template作为要生成的html的模板 }) ]}
上面代码中的template这里是一个html,官方的介绍是,你可以使用jade或ejs等模板引擎,也就是说webpack不关心你使用什么作为模板,只要输出一串字符串就行,于是我大胆的使用一个js文件作为模板,输出一段字符串,结果完全可行。
这样就产生了很多种方案,比如用js文件作为模板,在这个js文件中require其他的html文件,进行字符串拼接,最后输出,但是这样的话,每个需要输出的页面都需要配置也个这样的js文件,懒惰的我不允许这种事情的发生…..
再比如,直接使用一个html作为模板,配合使用html-loader,这个loader有一种引入其他文件的语法支持:
<div> ${require('./components/gallery.html')} </div>
这样我们就能引入其他的文件模块…..
但是有的时候我们需要一些模板语法,例如我们需要循环生成li
标签,最后我采用的方案是使用 ejs
作为模板文件,采用 underscore-template-loader
作为我的loader,而没有采用 ejs-loader
,因为 ejs-loader
不会处理文件html结构中的图片路径问题,而且 ejs-loader
也没有require其他ejs文件的语法支持,虽然 ejs-loader
官方推荐使用 ejs-compiled-loader
用它来引入其他的ejs模块,但是这样显得很麻烦,而且图片路径问题还是没有解决。然后我就找到了神器 underscore-template-loader
,首先图片路径问题loader会帮你解决,其次该loader支持两种require其他文件的语法:
<div class="top-section"> @require('header.ejs', {"title": "First Section"})</div>
这里引入一个ejs文件,并向其中传入对应的值。(如果你看不懂上面的代码,可以先熟悉一下ejs语法)这样就能很轻松的引入一个component文件,并传入值,此外,如果你只想引入一段不带语法的html结构(即纯字符串),也可以采用下面的写法
<div class="wiki"> <h3>Introduction</h3> @include('intro.htm') <h3>Authors</h3> @include('authors.htm')</div>
include只会将文件转换成字符串,并引入,所以确保你要引入的文件没有被loader处理过,不然很可能引入的是一个函数,而不是一串html结构。我在layout目录下设置不同的文件夹,一个文件夹代表一个页面,其中的ejs文件作为html-webpack-plugin的template,用这个ejs文件去require其他的component,如下图:
到这里我,我们基本都已经解决了html结构的部分,那css应该写在哪里呢?另外我不想把css也打包在bundle.js中,我想要生成单独的css文件,怎么办?
生成CSS文件
extract-text-webpack-plugin的使用
下面我们介绍另外一个webpack的插件:extract-text-wepack-plugin
,这个插件用于提取出css文件。
我把一个页面的css放在layout下(这里我用的是sass),用这个css去require其他的component的css,如下图:
这个总的css是有了,可是我们把它放在哪呢?任何资源只有被入口的js文件require,才能被webpack处理,所以我们当然是用layout下的入口js文件去require这个css,但是这样css也就会被打包到bundle.js中,于是我们可以在这里使用extract-text-wepack-plugin
怎么用呢?主要是两步:
首先在rule中,对所有的scss文件使用extract-text-wepack-plugin
rules: [{ test: /\.scss$/, use: ExtractTextPlugin.extract({ fallback: "style-loader", use: ["css-loader?importLoaders=2","postcss-loader","sass-loader"] })}]
其次在plugin中使用extract-text-wepack-plugin
:
plugin: [new ExtractTextPlugin('[name]/[name].css')]
特别注意,我们还需要在webpack.config.js文件的头部引入extract-text-wepack-plugin
这个模块,不然ExtractTextPlugin 就会没有定义,从而报错:
const ExtractTextPlugin = require("extract-text-webpack-plugin");
打包一下,在dist文件下,就能看到我们需要的css文件了。并且生成好的html也自动引入了这个css文件。
如何热更新?
当我们开启webpack的webpack-dev-server后,发现改动html和css都不能产生热更新,只有改动js才能热更新,我们可以在github官方页面上找到答案,如下图:
也就是说 extract-text-webpack-plugin
不支持热更新,于是我们可以这样来改进它,使用两种环境,一种是开发环境,一种是生产环境,在开发环境中,我们用入口的js去 require
layout
文件下的ejs模板,而不再使用html-webpack-plugin生成。也就是说,在开发的时候,所有的资源都是打包在bundle.js文件中的,只有在生产的时候,才像上面我们说的那样生成html和css,大概思路就是这样,那我们可以写两份不同的webpack的config文件,一个是开发另一个用作生产。
但是我只用了一个webpack.config.js,我们可以使用node提供给我们的一个API,来设置一个全局的值,使用方法如下:
//package.json"scripts": { "build": "set NODE_ENV=production&& webpack -p --color"}
使用set NODE_ENV=production
就可以设置这个全局的值了,这里设置的是production,注意: production
和&&
之间不能有空格,不然这个全局的值就设置成'production '
,production后面多了一个空格,怎么获取这个值呢?我们可以在程序的任意位置,通过process.env.NODE_ENV
来拿到这个值,做一个 if
判断就可以知道是开发环境还是生产环境了。
以css为例,配置如下:
rules: [{ test: /\.scss$/, use: process.env.NODE_ENV == 'production' ? ExtractTextPlugin.extract({ fallback: "style-loader", use: [ "css-loader?importLoaders=2", "postcss-loader", "sass-loader" ] }) : ['style-loader','css-loader?importLoaders=2',"postcss-loader",'sass-loader']}]
这样就可以用一份配置实现不同的需求,当然,我们还可以使用webpack提供的一个插件:DefinePlugin
把这个值暴露给整个webpack
plugin: [new webpack.DefinePlugin({ 'ENV': JSON.stringify(process.env.NODE_ENV)//获取到NODE_ENV的值,并暴露为全局变量 })]
这样我们在任意的地方都可以直接使用ENV
这个值了。
到这里就结束了,抛砖引玉说了一下大致的思路,没有展开谈具体细节,我把这个脚手架开源在github上,(https://github.com/cwj0130/webpack-cli),大家可以clone参看具体细节,我也在完善部分功能,例如单元测试等,如果此教程对您有帮助,麻烦在github上给个star,谢谢。
此文为原创,可以任意转载,但请标明出处。
- webpack生成html文件,用于后端渲染的研究
- webpack自动生成项目中的HTML文件
- 后端渲染和前端渲染的比较
- 前端渲染与后端渲染的区别
- 前端渲染和后端渲染的区别
- webpack打包生成的bundle.js文件过大的问题
- 【Web】artTemplate模板引擎:编译(生成渲染函数)+渲染(生成HTML串) 模板:基于JS的语法(JS+自定义)+HTML
- 用于生成DLL文件的def文件的规范写法
- gsoap:编写用于soapcpp2.exe生成文件的头文件
- 关于后端渲染html页面给游览器
- 生成html格式的文件
- 前后端渲染页面的区别?
- 前端渲染和后端渲染,要说的都在这里?
- HTML的渲染原理
- HTML的渲染过程
- 用于生成WSC文件的Script Component Wizard
- java生成固定格式的XML文件,用于报表
- 自己生成keystore文件,用于打包release版本的APK
- Qt 解决界面切换时的闪烁问题
- 系统恢复
- UVa 247 Calling Circles 经典floyd传递闭包
- ora-00923:未找到要求的form关键字
- 实现启动动画的一种方法
- webpack生成html文件,用于后端渲染的研究
- Codeforces Round#321 (div.2) A,B,C,D;(细节处理,尺取,dfs(树上的),状态压缩dp)
- 基于51单片机矩阵键盘程序
- kaggle之泰坦尼克号
- DevOps 初学者宝典
- 运用java.net.HttpURLConnection实现java多线程下载文件
- 1662 家庭问题
- 百度地图开发(功能有:标注地点;定位本机等)
- bootstrap轮播图无法居中的处理方式