# xsloader4j
**Repository Path**: ApeCoder/xsloader4j
## Basic Information
- **Project Name**: xsloader4j
- **Description**: 让java web项目支持JavaScript ES6+(ES2015,ES2016,ES2017,ES2018)、*.scss、*.less、*.vue、*.jsx。
- **Primary Language**: Java
- **License**: Apache-2.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 15
- **Created**: 2022-02-09
- **Last Updated**: 2022-02-09
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
## 一、项目介绍
让java web项目支持JavaScript ES6+、*.scss、*.less、*.vue、*.jsx、*.ts等。
## 二、版本
当前最新版本为 [**1.3.5**](https://mvnrepository.com/artifact/com.xishankeji/xsloader4j-core)


[Github](https://github.com/gzxishan/xsloader4j)
[码云](https://gitee.com/xishankeji/xsloader4j)
## 三、运行环境
- JDK 8
- servlet3
- Windows,Linux,Mac
- maven3
#### 推荐IDE
- idea
#### 已测试环境
- Jdk8
- Windows10,windows server 2018
- CentOS 7.4,7.5,7.8,7.9
- 注意(WARNING):linux环境可能需要升级libstdc++.so
```
非root用户可以使用以下方式:
export LD_PRELOAD=/.../libstdc++.so.6.0.28
```
## 四、安装
- spring boot版
```xml
com.xishankeji
xsloader4j-spring-boot-embed-starter
1.3.5
```
- 普通servlet版(项目以war包形式运行在tomcat、jetty等容器下)
```xml
com.xishankeji
xsloader4j-core
1.3.5
```
## 五、配置
### 1、启动配置
在资源目录(如src/main/resources)下新建xsloader4j.properties:
- xsloader.js加载器访问路径为:/contextPath/xsloader.js
```properties
xsloader.es6.polyfill=true
xsloader.es6.debug=true
xsloader.es6.name=default
xsloader.sourcemap=true
xsloader.es6.dealt.ignores=
xsloader.es6.dealt.static=
xsloader.es6.extensions=
xsloader.es6.detectBrowser=true
xsloader.es6.v8flags=
xsloader.conf.properties.staticUrlPrefix=https://xxxxx.cn/xxx
xsloader.conf.properties.prop1=xxx
xsloader.htmv.enable=false
xsloader.htmv.paths[0]=* to /WEB-INF/htmv/default.html
xsloader.htmv.paths[1]=/mobile/ to /WEB-INF/htmv/mobile.html
xsloader.react.autojs=true
xsloader.react.product=true
xsloader.htmr.paths[0]=* to /WEB-INF/htmr/default.html
xsloader.htmr.paths[1]=/mobile/ to /WEB-INF/htmr/mobile.html
xsloader.ctrl.enable=false
xsloader.embed.enable=true
```
- xsloader.es6.polyfill:是否使用polyfill,为true时、会自动加载polyfill,默认为true。
- xsloader.es6.debug:是否为debug模式,当为true时,文件修改后会重新进行转换。
- xsloader.es6.name:目录名,默认default,当多个项目的临时为目录相同时、可避免v8加载失败。
- xsloader.sourcemap:是否转换source map。
- xsloader.es6.dealt.ignores:忽略转换的目录,用逗号分隔,如“/static/lib1,/static/lib2”。
- xsloader.es6.dealt.static:静态资源在资源目录下的路径(在spring boot嵌入式版本中使用),如“/static”,多个用逗号分隔。
- xsloader.es6.extensions:脚本后缀,可以省略里面指定的后缀名(但路径中必须含有/分隔符),默认为".js,.vue,.jsx,.ts,.jsr,.jtr,/index.js,/index.vue,/index.jsx,/index.ts,/index.jsr,/index.jtr"
,且取值只能是[.js,.vue,.jsx,.ts,.jsr,.jtr,/index.js,/index.vue,/index.jsx,/index.ts,/index.jsr,/index.jtr]中的值
- xsloader.es6.detectBrowser:是否根据浏览器版本,进行不同级别的js转换。默认true。
- xsloader.conf.properties.xxx:参数可直接在xsloader配置文件里使用`#{propName}`进行引用。
- xsloader.htmv.enable:是否启用htmv,默认为false
- xsloader.htmv.paths:配置默认的html模板(可选)。`classpath:`开头表示资源目录,其他表示在web路径下(通过`servletContext.getRealPath`获取)
- xsloader.conf.forceCacheSeconds:配置被浏览器强制缓存的时间
- xsloader.es6.versionAppendTag:如果设置了该标记,当文件变化后,会在该标记后添加文件版本(支持的文件为所有需要转换的文件);该标记右边加`,`表示需要前置逗号;
- xsloader.react.autojs:默认为true,是否导入内置的react依赖。
- xsloader.react.product:默认为true,使用内置react依赖时,是否为产品模式。
- xsloader.ctrl.enable:默认为true,是否在响应的配置里添加控制参数。
- xsloader.embed.enable:默认为true,全局的`//!embed`开关。
### 2、xsloader配置
在资源目录(如src/main/resources)下新建xsloader-conf.js,参考内容如下:
- 该配置文件的访问路径为:/contextPath/xsloader.conf
- 注意此配置文件为JS版的json对象,支持JS脚本。
- 关于此文件配置的更详细说明见:[xsloader模块加载器配置](https://github.com/gzxishan/xsloader/wiki/7.xsloader配置服务)
- 通过`#{propName}`引用配置参数,contextPath默认为当前servlet的context path参数。
- 此配置文件缓存时间为30秒,通过urlArgs可以控制其他资源的版本,从而有效避免缓存问题。
```JavaScript
{
"properties":{
"contextPath":"#{contextPath}",
"staticUrlPrefix":"#{staticUrlPrefix}",
"libReplace":{
"libxs/":{
"replace":"${staticUrlPrefix}/libxs/"
},
"lib/":{
"replace":"${staticUrlPrefix}/lib/"
},
"libui/":{
"replace":"${staticUrlPrefix}/libui/"
}
}
},
"main":{
getPath:function(dataMain){
return dataMain||"./es-main/{name}.js";
},
"before":function(){
console.log("before:" + name);
},
"after":function(){
console.log("after:" + name);
}
},
"chooseLoader":function(localConfig){
var path=this.getPagePath();
if(xsloader.startsWith(path,"/test1/")){
return "test1";
}else if(xsloader.startsWith(path,"/test2-no-vue/")){
return "test2-no-vue";
}else{
return "test1";
}
},
"loader":{
"test1":{
"baseUrl":"${contextPath}/",
"modulePrefix":"$[libReplace]",
"urlArgs":{
"*[${contextPath}/":"v=20200130-02",
"*[libxs/":"v=20200129-3",
"*[lib/":"v=190109-26",
"*[libui/":"v=190109-26"
},
"paths":{
"vue":"static/vue/vue.min.js"
},
"deps":{
"*":"vue"//当有vue组件或jsx语法时,一定要先加载vue模块
}
},
"test2-no-vue":{
"baseUrl":"${contextPath}/",
"modulePrefix":"$[libReplace]",
"urlArgs":{
"*[${contextPath}/":"v=20200130-02",
"*[libxs/":"v=20200129-3",
"*[lib/":"v=190109-26",
"*[libui/":"v=190109-26"
},
"paths":{
},
"deps":{
}
}
},
"getPagePath":function(){
var path=location.pathname.substring(this.properties.contextPath.length);
return path;
},
"sporter":"${contextPath}/",
"fromPath":function(path){
return location.protocol+"//"+location.host+this.sporter+path;
},
"beforeDealProperties":function(){
}
}
```
## 六、使用与demo运行
- xsloader脚本引入:
```html
```
- 配置文件引入:直接在xsloader.js的script标签上,设置属性data-conf2
```
data-conf2="./xsloader.conf"
```
- 详细例子可以参考demo-servlet项目
- demo-servlet为普通servlet项目,执行jetty:run或tomcat7:run的maven插件,可运行demo。
访问地址:[http://localhost:8070/index.html](http://localhost:8070/index.html)
- demo-spring-boot-servlet为spring boot servlet项目
- demo-spring-boot-main为spring boot main函数项目(普通java项目)
- test1目录结构:
```
/test1/
/test1/index.html
/test1/es-main/index.js
/test1/es-main/vue/comp1.vue
/test1/es-main/jsx/comp2.jsx
```
### index.html
```html
测试1
```
### comp1.vue
```vue
{{info}}
$thiz.getUrl():{{$thiz.getUrl()}}
$thiz.getUrl("../index.js"):{{$thiz.getUrl("../index.js")}}
```
### comp2.jsx
```jsx
export default {
render(){
return (
)
}
}
```
### index.js
```JavaScript
import "css!static/test.scss";//不是以“.”开头的路径相对于baseUrl
import Vue from "vue";
import comp1 from "./vue/comp1.vue";//需要加入文件后缀,当前目录需要用"./"、否则是相对于baseUrl
console.log(thiz.getUrl());//http://localhost:8070/test1/es-main/index.js?v=20200130-02
console.log(thiz.getUrl("./lib/other.js"));//http://localhost:8070/test1/es-main/lib/other.js?v=20200130-02
new Vue({
el:"#vue-app",
template:"#app-template",
methods:{
getVnode(){
return (
来自函数
);
},
onClickVnodex($event){
alert("onClickVnodex:"+$event);
},
onClickp($event){
alert("onClickp:"+$event);
}
},
components:{
comp1,
comp2:()=>import("./jsx/comp2.jsx")//支持异步加载
}
});
```
## 七、其他说明
### 1、打包说明
- 打包成指定系统的war包后会增加20Mb左右,例如打包到linux系统下运行,可在`pom.xml`的plugins里排除windows与mac的j2v8依赖包:
```xml
maven-war-plugin
3.2.2
WEB-INF/lib/j2v8_win**.jar,WEB-INF/lib/j2v8_macosx**.jar,
```
- 若在mac下运行,需要自行加入依赖:
```xml
com.eclipsesource.j2v8
j2v8_macosx_x86_64
4.6.0
```
### 2、引入其他库
- 引入的第三方库需要遵循AMD规范
- 一般打包的三方umd模块可以正常工作,可以参考项目`demo-servlet`
- `注意`:import其他组件或模块,可省略的后缀见`xsloader.es6.extensions`配置
### 3、代码转换说明
#### 1.1)*.js
- 语法支持到es2018
- 支持jsx语法
- 某些IDE暂不支持jsx语法,可以用如下方式勉强避免错乱:(编译前,java后台会把Vue文件里的\`\jsx与\jsx\`删除)
- 内置``组件(需要全局配置vue模块),通过x属性(返回jsx对象的函数或jsx对象,支持字符串等内容)可以直接显示编译后的jsx对象
```
```
- 自动判断js文件语法,当具有以下语句之一时,则会进行转换:
```javascript
let ...
import ...
export ...
const ...
```
-
thiz变量指向当前模块,更多请见[xsloader的this](https://github.com/gzxishan/xsloader/wiki/2.define,require,invoker%E7%AD%89#5this%E4%B8%8E_invoker_)
- 当有vue组件、jsx语法或htmv时,需要在配置文件的loader里设置vue2依赖:
```json
{
"paths": {
"vue": "你的vue2的路径/vue.min.js"
},
"deps": {
"*": "vue"
//当有vue组件、jsx语法或htmv时,一定要先加载vue模块
}
}
```
#### 1.2)*.ts
- typescript脚本;
- 不支持jsx语法;
#### 2)*.vue
```html
```
- \
```
- `script`的`lang`支持`typescript`或`ts`
- 通过settings注释里的json格式对文档进行设置:
1. title:设置文档标题
2. noLoadingMask:当此值设置为true时,将去掉id为`loading-mask`的加载框。
3. heads:用于添加到``标签中
- 通过浏览器可以直接访问htmv文件(java端会自动转换),参考demo-servlet的test1/index.htmv。
- 当有vue组件、jsx语法或htmv时,需要在配置文件的loader里设置vue2依赖:
```json
{
"paths": {
"vue": "你的vue2的路径/vue.min.js"
},
"deps": {
"*": "vue"
//当有vue组件、jsx语法或htmv时,一定要先加载vue模块
}
}
```
- 通过设置`xsloader.htmv.enable=true`来启用htmv
#### 3.2)*.htmr
- 该文件实际是一个jsr格式的文件,更多说明见*.jsr
- htmr文件无``,html注释``后面需有换行,`
```
- `script`的`lang`支持`typescript`
- 通过settings注释里的json格式对文档进行设置:
1. title:设置文档标题
2. heads:用于添加到``标签中
- 通过浏览器可以直接访问htmr文件(java端会自动转换)。
- 通过设置`xsloader.htmr.enable=true`来启用htmr
- 若`xsloader.react.autojs`为false需要配置`react`与`react-dom`依赖
#### 4)*.scss
支持scss语法
#### 5)*.less
支持less语法
#### 6)*.jsx
- 效果与*.js文件效果是一样的
- 当有vue组件、jsx语法或htmv时,需要在配置文件的loader里设置vue2依赖:
```json
{
"paths": {
"vue": "你的vue2的路径/vue.min.js"
},
"deps": {
"*": "vue"
//当有vue组件、jsx语法或htmv时,一定要先加载vue模块
}
}
```
- 属性、class、事件等设置见Vue的$createElement
```
详细属性:
{
//class:接受一个字符串、对象或字符串和对象组成的数组
'class': {
foo: true,
bar: false
},
//style:接受一个字符串、对象,或对象组成的数组
style: {
color: 'red',
fontSize: '14px'
},
//普通的HTML特性
attrs: {
id: 'foo'
},
//组件prop
props: {
myProp: 'bar'
},
//DOM属性
domProps: {
innerHTML: 'baz'
},
// 事件监听器在`on`属性内,
// 但不再支持如`v-on:keyup.enter`这样的修饰器。
// 需要在处理函数中手动检查keyCode。
on: {
click: this.clickHandler
},
// 仅用于组件,用于监听原生事件,而不是组件内部使用
// `vm.$emit` 触发的事件。
nativeOn: {
click: this.nativeClickHandler
},
// 自定义指令。注意,你无法对 `binding` 中的 `oldValue`
// 赋值,因为 Vue 已经自动为你进行了同步。
directives: [
{
name: 'my-directive',
value: '2',
expression: '1 + 1',
arg: 'foo',
modifiers: {
bar: true
}
}
],
//作用域插槽的格式为
//{ name: props => VNode | Array }
scopedSlots: {
default: props => createElement('span', props.text)
},
//如果组件是其它组件的子组件,需为插槽指定名称
slot: 'name-of-slot',
// 其它特殊顶层属性
key: 'myKey',
ref: 'myRef',
//如果在渲染函数中给多个元素都应用了相同的 ref 名,
//那么`$refs.myRef` 会变成一个数组。
refInFor: true
}
```
#### 7)*.jsr,*.jtr
- *.jtr后缀的语言为typescript
代码为react模式,脚本语法同js,jsx属性见react(不同于vue的)。
#### 8)文件合并说明
可以通过`//!embed`将脚本(只对需要进行代码转化的有效)直接内嵌到当前文件。
- 支持递归
- 注意:后缀名不能省略
```
//!embed
import "./embed/a.js";
import "./embed/b.js";
//!embed
```
#### 9)sourcemap源码
转换的源码可在浏览器控制台Sources标签下,对应页面的`/$$xs-sources$$/`路径下找到,支持脚本断点调试。
### 4、polyfill
您可能需要使用polyfill来更好的使用es6+代码,如Map、array.includes、string.startsWith、async/await等
- 默认xsloader.es6.polyfill为true,会自动加载polyfill。
- 在本项目polyfill/目录下下载了些版本的js文件
- 可以去https://babeljs.io/docs/en/babel-polyfill/下载
```bash
cnpm install --save @babel/polyfill
在node_modules/下对应目录下去复制polyfill.js文件
```
### 5、xsloader.js说明
该插件是基于AMD协议开发的模块加载器(借鉴了requirejs,但从1.2.x开始进行了重构),支持异步模块加载、插件开发、更灵活的依赖配置、脚本版本配置等。
内置插件包括:css、image、json、text、request、ifmsg等。
[xsloader-wiki](https://github.com/gzxishan/xsloader/wiki)
### 6、直接获取源码
在请求地址上加入`__source=true`则直接返回源码。
## 八、发布记录
### v进行中
### 1.3.5 2022/01/10
1. 升级`babel`版本为`7.15.3`;
2. 升级`vue`版本为`2.6.14`;
3. 使用`javet`的`v8`引擎;
4. 完善`es6`代码的判断;
5. `//!embed`嵌入模式的开始标签支持`//!embed:all`,用于递归嵌入所有相对页面(需含有后缀);
6. 完善`vue`模板文件解析;
7. `jsx`支持`Promise`;
8. `htmv`增加`settings.noLoadingMask`属性;
### 1.2.108 2021/08/24
1. 完善`xsloader`的`ifmsg`连接流程;
2. `xsloader.appendArgs2Url(url, urlArgs, encoding = false)`增加`encoding`选项;
3. `xshttp`增加`rhandle`属性;
4. 解决`//!embed`嵌入模式不支持`./xxx!`插件的问题;
5. 完善`xsloader`的`css`插件样式加载顺序;
6. 修复`xsloader`的插件`willCache`处理问题;
### 1.2.97 2021/07/29
1. `ifmsg`的`client`加入`request`(返回`Promise`)与`onRequest(data,resolve,reject)`;
2. 修复`.vue`的``里出现`