JS模块化工具 requirejs 学习文档
作为一个Java开发者,原来写js代码都是流水账式的,一直想写出模块化的js,但是前端工具多如牛毛,确都是针对于nodejs的打包工具。但是我在实际的开发过程中,并没有使用到太多的js库,一般只使用到boostrap、jquery和其相关的插件,并不想引入nodejs和各种前端插件来增加项目的复杂度。requirejs完全符合我的要求,还可以配合maven实现自动打包和压缩代码。下面我们来简单介绍一下requirejs,实现在开发阶段,不打包,不压缩,模块化开发;部署阶段,自动打包、压缩。
requirejs简介
requirejs是JS模块化开发的框架,它遵循AMD(Asynchronous Module Definition)规范,实现js脚本的异步加载,不阻塞页面的渲染和其后的脚本的执行。使用requirejs可以简化js的依赖,我们无需在html文件中使用<script>
标签引入大量的js文件,只需引入少量的require.js
文件,其他的js文件都可以通过requirejs引入。
什么是AMD
define(id?, dependencies?, factory);
- Id:模块名,可以省略
- Dependencies:所依赖模块的数组,可以省略
- Factory:模块的实现,可以是函数或对象
requirejs安装
- 使用npm
npm install –g requirejs
- 使用CDN
<script src="https://cdn.bootcss.com/require.js/2.3.5/require.js"></script>
- 使用本地文件
<script src="scripts/require.js"></script>
如果需要使用其他的js,只需在require。config.js之中导入对应模块即可。
requirejs常用Api
require导入模块
在模块中引入其他模块的语法为:
require(['jquery'], function($) {
//回调函数
});
在回调函数中我们就可以使用jquery中的$
符号了。
当然我们只会引用其他的模块是肯定不行的,我们还需要定义符合AMD规范的模块。
define定义模块
自定义模块的语法为:
define(["jquery"], function($) {
});
define({
username: "yoojoo",
email: "yookoo@163.com",
gender: "男"
})
这个模块是一个依赖于jquery的匿名模块,在requirejs中定义匿名模块也是模块定义的最佳实践,他将以对应的文件名作为模块的模块名。
常用配置
requirejs.config({
baseUrl: '/public/js',
paths: {
hello: 'hello'
},
shims: {
hello: { exports: 'hello' }
}
});
baseUrl配置
baseUrl用于配置js文件的根目录
baseUrl: '/public/js',
paths配置
paths用于配置js模块的模块名和文件位置
paths: {
"jquery": "./lib/jquery.min"
}
上面表示jquery的js文件位置为public/js/lib/jquery.min.js
配置不支持AMD的库和插件
shims、exports、deps配置
shim:{
"modernizr": { //不支持AMD的模块
depts:["jquery"], //依赖的模块
exports: "Modernizr",//全局变量作为模块对象
init : function($){
return $; //初始化函数,返回的对象代替exports作为模块对象
}
},
"bootstrap": ["jquery"] //只配置依赖可以省略
}
map多版本配置
项目开发初期使用jquery1.12.3,后期以为需要支持移动开发,升级到jquery2.2.3。但是又担心之前依赖jquery1.12.3的代码升级到2.2.3后可能会有问题,就保守的让这部分代码继续使用1.12.3版本
map: {
"app/api":{
"jquery": "./lib/jquery"
},
"app/api2":{
"jquery": "./lib/jquery2"
}
}
当app/api模块里加载jquery模块时,将加载jquery.js
当app/api2模块里加载jquery模块时,将加载jquery2.js
waitSeconds
下载js等待的时间,默认7秒。如果设为0,则禁用等待超时。
urlArgs
下载文件时,在url后面增加额外的query参数
e.g. urlArgs: “_=" + (new Date()).getTime()
jsonp服务
什么是jsonp
是json的一种使用模式,可以跨域获取数据,如json
同源策略:www.baidu.com通过ajax不能获取www.qq.com的数据
传统的jsonp实现
//www.qq.com中
<script src="http://www.baidu.com/user?callback=onloaded"></script>
//在www.baidu.com/user下
onload({
username: "yoojoo",
email: "yookoo@163.com",
gender: "男"
})
这样通过<script>标签就实现了跨域请求
requirejs的jsonp实现
requirejs也是通过<script>标签来加载模块
//www.qq.com中
require(["http://www.baidu.com/user],function(){
});
//在www.baidu.com中
define({
username: "yoojoo",
email: "yookoo@163.com",
gender: "男"
});
requirejs插件
text插件
使用text插件加载html
text插件Github
引入text插件
paths:{
"text": "./lib/require/text"
}
使用text插件
require(["text!/user.html"],function(template){
$("#userinfo").html(template);
});
//!strip表示只加载body内的数据
require(["text!/user.html!strip"],function(template){
$("#userinfo").html(template);
});
css插件
css插件的Github地址
引入css插件
//方法一:通过map引入
map {
"*" {
"css": "./lib/require/css"
}
}
//方法二:在paths中引入
paths: {
"css": "./lib/require/css"
}
使用css插件
//方法一:在require中引用
require(["jquery","bootstrap",""css!./lib/bootstrap/bootstrap.min.css""],function($){
});
//方法二:在slim中配置依赖后,在require中引用时可以省略css
shim: {
"bootstrap" : ["jquery","css!./lib/bootstrap/bootstrap.min.css"]
}
r.js打包
r.js打包命令
- 全局安装requirejs
r.js –o baseUrl=js name=app out=built.js
- 运行github中下载的r.js
node r.js –o baseUrl=js name=app out=built.js
使用配置文件打包
node r.js -o app.build.js
//app.build.js
({
appDir : "./src", //需要打包的根目录
baseUrl: "./js", //js文件在baseUrl目录下
dir: "./build", //打包后的输出目录
mainConfigFile: "src/js/require.config.js" ,//requirejs的配置文件
name: "app" //打包和输出的文件
})
modules 配置
数组:列出所有需要打包的模块,当打包一个模块时,默认会打包所有依赖的模块
text打包插件
inlineText配置项:是否把文本文件一起打包进模块
css打包插件
css打包插件
通过css-builder.js和normalize.js把css文件和模块一起打包
使用npm命令自动打包
- npm init生成package.json文件
- 在script 中配置打包命令
"script": {
"package": "node r.js -o app.build.js"
}
npm run package
maven打包
使用maven+npm自动打包
maven插件
npm打包缺点:手动打包会有出错的地方,比如开发人员忘了执行打包命令,就提交代码,服务器端在自动部署代码的时候,打包的jar就不包含最新的js和css,这时候就用到了我们的maven插件frontend-maven-plugin
可以再打包java文件之前自动打包js文件
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>1.0</version>
<executions>
<!--下载安装node-->
<execution>
<id>install node and npm</id>
<goals>
<goal>install-node-and-npm</goal>
</goals>
<configuration>
<nodeVersion>v4.4.3</nodeVersion>
<npmVersion>3.8.6</npmVersion>
</configuration>
</execution>
<!--执行npm命令-->
<execution>
<id>npm run package</id>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>run package</arguments>
</configuration>
</execution>
</executions>
</plugin>
执行流程
- 下载node和npm,如果已经下载过一次,就从maven仓库解压
- 在生成静态资源阶段,执行npm命令
- 执行java的单元测试,打包完成