WEBPACK + JSP 构建多页应用

概述

传统的JSP页面应用无法有效的使用ES6语法特性,项目打包压缩困难,无法热更新。传统的单页应用在Tomcat等容器下无法进行服务端渲染到达SEO的效果。本项目工程很好融合的传统JSP页面服务端渲染的特点和单页应用开发特性且极易上手使用!

源码地址

源码地址

Demos与文档

Demos与文档

特性

  • 多页应用
  • JSP嵌套
  • el表达式
  • 服务端渲染(SEO)
  • 热部署
  • js,css语法转换
  • eslint
  • 热更新
  • 支持Vue
  • 打包压缩
  • IE9+
    支持传统JSP开发所的所有功能;可以通过自定义webpack配置来实现对react的支持;通过引入vue-router和vuex某一个页面完成可以变成一个单页应用。

如果您想要支持IE8,那需要把webpack降级,因为webpack2+是不支持IE8的,以及尽量避免去使用不支持IE8的库,比如jquery2+,lodash4+, Vue等,祝您好运。

环境搭建

工欲善其事,必先利其器。

  • JDK1.7+
  • IntelliJ IDEA,需要安装js相关插件和配置支持es6语法。
  • Maven3+
  • Tomcat7+,端口默认请使用8080
  • Git bash
  • npm3+
  • node7+

如果您喜欢编辑js和css的时候用vscode也是没有问题,不过编写jsp和java还是推荐用idea。

以下总结环境配置的相关文章,可供参考
JDK下载地址
IntelliJ IDEA配置前端开发环境
IntelliJ IDEA配置JAVA WEB的Tomcat环境
maven下载安装
Git Bash下载安装

目录说明

├── pom.xml   // maven配置文件
├── src
|  ├── main
|  |  ├── filters
|  |  |  └── resources // java工程资源配置目录
|  |  ├── java // java代码目录
|  |  ├── js // 前端页面工程
|  |  |  ├── build  // 编译相关以及webpack相关配置
|  |  |  |  ├── build.js
|  |  |  |  ├── check-versions.js
|  |  |  |  ├── logo.png
|  |  |  |  ├── utils.js
|  |  |  |  ├── webpack.base.conf.js
|  |  |  |  ├── webpack.dev.conf.js
|  |  |  |  └── webpack.prod.conf.js
|  |  |  ├── config // 配置相关
|  |  |  |  ├── dev.env.js
|  |  |  |  ├── index.js
|  |  |  |  ├── js-jsp-map.js // 配置入口js和jsp的映射
|  |  |  |  └── prod.env.js
|  |  |  ├── package.json // npm配置
|  |  |  ├── src // web项目工程目录
|  |  |  |  ├── pages // jsp页面,最终的jsp文件们会按照pages相对路径打包进webapp/WEB-INF/jsp目录下
|  |  |  |  |  ├── include // 共享的jsp页面,通过jsp:include引入
|  |  |  |  |  |  ├── common_script.jsp
|  |  |  |  |  |  ├── footer.jsp
|  |  |  |  |  |  ├── header.jsp
|  |  |  |  |  |  ├── init.jsp
|  |  |  |  |  |  └── meta.jsp
|  |  |  |  |  ├── index // 页面1
|  |  |  |  |  |  ├── index.js // 需要在在config/js-jsp-map.js配置与jsp的映射关系,这样编译后的js会加载jsp的body下。一般js与jsp在同一个目录下。
|  |  |  |  |  |  └── index.jsp
|  |  |  |  |  └── start // 页面2
|  |  |  |  |     ├── dashboard.css
|  |  |  |  |     ├── index.js
|  |  |  |  |     └── index.jsp
|  |  |     |     └── my-component.vue 支持VUE
|  |  |     ├── polyfills 兼容相关的代码
|  |  |     |  ├── console.js
|  |  |     |  ├── index.js
|  |  |     |  └── promise.js
|  |  |     ├── static // 存在静态文件,最终这些文件会拷贝到webapp目录下
|  |  |     |  ├── favicon.ico
|  |  |     |  ├── images
|  |  |     |  |  ├── jsp.svg
|  |  |     |  |  └── webpack.svg
|  |  |     |  ├── js
|  |  |     |  |  └── lib
|  |  |     |  |     └── jquery.min.js
|  |  |     |  └── WEB-INF
|  |  |     |     ├── tld
|  |  |     |     └── web.xml
|  |  |     └── styles
|  |  └── webapp // 该目录下的文件不用开发人员手动添加修改,在npm run dev或npm run build的时候自动生成。
|  └── test
|     └── java

src/main/js目录下的目录结构是在vue-cli的webpack模板的基础上修改的,如果您使用过该模板创建过项目,那么将很容易会上手。

开发

cd src/main/js
npm run dev

在idea中启动tomcat

在浏览器中打开http://localhost:8081

以下几点需要注意一下

首次启动项目,建议先npm run dev在启动tomcat。之后其中一个重启,另外一个可以不用重启。
默认情况下npm run dev跑在8081端口下,tomcat跑在8080端口下。最终在浏览器访问只需要访问8081的页面,8080页面没有必要。
开发模式下,js引入的css是动态引入的,页面会出现闪变的效果。不用担心,在发布后的环境中是不会出现的。
开发jsp页面的时候,热部署会有延时,具体参看JSP页面这一章节
开发jsp文件务必在pages目录下开发,切勿在webapp目录下开发。否则在切换到pages目录下开发或者打包后或,webapp下的jsp的文件会被覆盖,导致修改的内容丢失。

打包发布

npm run build

webapp作为输出目录,static中文件会拷贝到输出目录,pages目录下的jsp文件会作为模板文件拷贝到webapp/WEB-INF/jsp目录下,与jsp关联的js入口会被合并压缩后引入到jsp文件的body中。jsp关联的css会被抽离出一个单个的css文件引入的jsp文件head中。

如果您打包后的应用的Application Context不是/, 比如是/app,即访问地址都是基于http://localhost:8080/app,那么打包的时候webpack的publicPath参数记得配置/app,且jsp页面中所有的地址都需要带上${pageContext.request.contextPath}/,在该项目框架中可以简写为${ctx}/

JSP页面

传统的JSP是在src/main/webapp下开发,在这个项目框架下开发jsp文件是在src/main/js/src/pages下开发。虽然开发目录不一致,但依然拥有传统jsp开发所有的特性。

  • 模板嵌套,比如使用<jsp:include page=''></jsp:include>或者<%@include file=""%>
  • el表达式,<c:set>, <c:if>, <c:forEach>等都可以使用
  • 嵌入Java代码 比如使用<% out.println("hello world"); %>
  • 支持热部署。配置好启动tomcat相关参数。在修改完jsp保存文件后,约10秒后刷新页面就可以看到页面的变化。如果等不及10秒或者页面一直不刷新,可以先点击idea菜单File->Syncronize>同步文件(快捷键Ctrl+Alt+Y),然后在点击Run的左侧第三个按钮后选择Update classes and resources手动更新,之后就刷新页面就可以看到最新出的页面。
    实际在npm run dev的时候,pages目录下的jsp会作为htmlWebpackPlugin插件的模板文件,每次修改pages下的文件都会被输出到webapp/WEB-INF/jsp下的相对目录。需要了解具体原理,请前往核心章节

自定义标签库

除了标准的c, fmt, fn标签库外,您也可以自定义标签库。

  • 首先在static/WEB-INF/tld新建一个tld,比如elftld
  • 然后jsp页面引入,<%@ taglib prefix="elf" uri="/WEB-INF/tld/elfunc.tld" %>

注意的是,在jsp页面的地址必须以/WEB-INF/开头,而实际开发jsp的路径是在js/src/pages目录下,导致idea无法正常解析pages目录下jsp中tld文件路径,在使用自定义标签的时候也无法自动补全。不过可以正常运行,实际开发过程影响不大。如果您有更好的解决方案,请与我们联系。

语法转换

因为了使用了webpack作为打包工具,您可以轻松对js和css进行语法转换,目前支持:

  • es6, stage-2
  • postcss
  • less, sass, scss 需要额外装对应的loader即可支持

热更新

在开发单页应用的过程中,有一个很棒的特性就是热更新,修改了js文件,页面实时就会触发更新。
在此项目框架下,您依然可以享受到热更新带来的喜悦,在您修改js和css的时候,页面都会实时触发更新。

VUE

该项目已经默认支持Vue。这一章节也是用VUE编写的,你可以尽情的享受VUE带来的编码的快乐。

  • 您可以给idea添加vue.js插件,这样也可以直接使用.vue文件。
  • js和css的语法转换在.vue文件中同样适用。

核心

该项目融合了webpack和jsp两者的特性实现了多页应用,这很酷。那到底是如何实现的呢。这里我们从搭建项目遇到的问题来讲讲最核心的几个问题是如何解决的。

HtmlWebpackPlugin

使用webpack实现多页应用,很容易联想到配置多个entry入口,每一个entry对应一个HtmlWebpackPlugin。jsp文件作为HtmlWebpackPlugin的模板文件,在entry的js在打包之后会插入到body下。该项目也是按照这样的搭建的。
这里有几点需要注意

  • HtmlWebpackPlugin解析jsp文件需要对应的loader,需要在webpack中配置{ test: /\.jsp$/, loader: 'raw-loader' },这里使用raw-loader进行纯文本拷贝。如果您有更适合jsp的loader,那么您可以赋予jsp文件特多的特性。
  • 因为jsp可以被嵌套,这些被嵌套的jsp,并不是入口的jsp。所有只有是入口的jsp在配合HtmlWebpackPlugin插件的会额外添加{inject: 'body'}参数
  • 那如何规定哪些jsp是入口文件呢?我们是通过配置来约定entry的js与jsp的关联关系,配置文件在config/js-jsp-map.js中。

proxy反代

tomcat是跑在8080端口下的,webpack-dev-server是跑在8081端口下的,是两个不同应用。那岂不是开发jsp要在tomcat下编写调试,开发js在webpack-dev-server调试。这样的话岂不是很麻烦。

庆幸的webpack-dev-server有一个proxy参数,我们利用proxy把访问webpack-dev-server的请求都反代到8080下。这样实际开发过程中浏览器只要打开8081端口页面就可以。这样就做到兼顾jsp服务端渲染的功能,以及webpack语法转换,热更新的功能。tomcat只有在必要的时候重启一下就好。
这里有几点需要注意

  • npm run dev和启动tomcat并没有顺序要求,不过在浏览器访问8081前需要把这两个服务都启动起来。
  • 当涉及到jsp文件有新增删除,或者static目录下的文件有新增编辑删除时,需要重新npm run dev和重启tomcat。记住一点,如果有文件新增和删除,最好都把这两个服务都重启一下肯定是没有问题的。

WriteFilePlugin

我们知道webpack-dev-server是使用内存中的文件系统。而jsp页面最终是要发布到tomcat的,内存中的jsp文件并不能被idea监听,这样即使最终输出的jsp发生改变也无法被deploy到tomcat。
庆幸我们找到了一个webpack的插件WriteFilePlugin,它能强制把webpack-dev-server程序的输出的文件写到磁盘文件系统上。
这里有几点需要注意

  • 虽然通过WriteFilePlugin的jsp文件输出到磁盘上了,但是因为不是通过idea直接修改,idea还是无法立刻同步这些文件。idea同步并发布jsp文件会有10s的延迟。如果等不及10秒或者页面一直不刷新,可以先点击idea菜单File->Syncronize>同步文件(快捷键Ctrl+Alt+Y),然后在点击Run的左侧第三个按钮后选择Update classes and resources手动更新,之后就刷新页面就可以看到最新出的页面。

结语

这个思路其实不仅适用tomcat下的jsp多页应用,同样也是适用node作为服务器的多页应用。Enjoy it!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容

  • 写在开头 先说说为什么要写这篇文章, 最初的原因是组里的小朋友们看了webpack文档后, 表情都是这样的: (摘...
    Lefter阅读 5,269评论 4 31
  • 在现在的前端开发中,前后端分离、模块化开发、版本控制、文件合并与压缩、mock数据等等一些原本后端的思想开始...
    Charlot阅读 5,428评论 1 32
  • 人的一生准能遇到一些人渣
    劉曉軍阅读 227评论 0 0
  • 这个是因为苹果解决Xcode ghost。把插件屏蔽了。解决方法命令运行:sudo /usr/libexec/xp...
    Smallwolf_JS阅读 238评论 0 0
  • 江南的水墨烟雨 北国的冰天雪地 塞北的马头琴音 巴蜀的肥鱼 爱琴海的圣托里尼 美丽的西西里 以及 盛夏五月的你 这...
    鱼丸粗面只要碗阅读 119评论 0 0