前言
来到新公司,接手一个一年前的老项目,项目技术栈为fis3+vue1+requireJs+less,从而接触到fis3+require.js的配合用法。虽然这套方案已经慢慢被遗弃,而fis3也被webpack逐步取代。但是学习这套方法对维护旧项目有不少的帮助,因此便记录一下学习过程。
简介
fis3 :是面向前端的工程构建工具。解决前端工程中性能优化、资源加载(异步、同步、按需、预加载、依赖管理、合并、内嵌)、模块化开发、自动化工具、开发规范、代码部署等问题。
require.js:一个能实现js文件的异步加载,避免网页失去响应和管理模块之间的依赖性,便于代码的编写和维护的JS库。
重点
require.js
//main.js会第一个被require.js加载
// main.js
require(['moduleA', 'moduleB', 'moduleC'], function (moduleA, moduleB, moduleC){
// some code here
//只有在module ABC都加载成功,回调函数才会执行
});
//配置require对象,写在main.js主体函数前
require.config({
baseUrl: "js/lib", //配置基准目录,可选
paths: { //定义依赖的名称和路径,默认加后缀.js,所以别加.js。定义后页面会自动加载此js文件,不用自己引入。
"jquery": "jquery.min",
"underscore": "underscore.min",
"backbone": "backbone.min"
},
shim: { //加载非amd规范的模块
'underscore':{
exports: '_'
},
'backbone': {
deps: ['underscore', 'jquery'], //模块依赖
exports: 'Backbone' //输出的变量名,表明这个模块外部调用时的名称
},
'jquery.scroll': { //jquery插件可以这样写
deps: ['jquery'],
exports: 'jQuery.fn.scroll'
}
}
});
//定义一个amd模块
//第一个参数为名字,可选,定义了名字可以让其他文件根据其名字找到这个模块,不用显式配置require.config的path,而且如果require.config的path定义的名称与这个参数不一致,前者会无效。
//第二个参数是依赖于其他模块,可选,必为数组。
//函数必定有返回值,一般为对象。
define('name', ['myLib'], function(myLib){
function foo(){
myLib.doSomething();
}
return {
foo : foo
};
});
正确姿势:
引入require.js, 用require.config的paths属性加载其他js文件,注意paths中的key要和js文件中define定义的name一致,不然会引入失败。如果define中没有传入name参数,则默认和key相同。
参考资料:
- http://www.ruanyifeng.com/blog/2012/11/require_js.html (阮一峰)
- http://blog.csdn.net/u010130282/article/details/52329953
fis3
常用命令
fis3 release -wL 打包并启动热加载,默认输出到内置服务器目录
fis3 server start 开启fis3内置服务器
fis3 server open 打开内置服务器的目录
fis3 release prod 打包成生产环境
重要知识
fis-conf.js为配置文件,放在项目根目录;
//selector :FIS3 把匹配文件路径的路径作为selector,匹配到的文件会分配给它设置的 props
//props :编译规则属性,包括文件属性和插件属性
//http://fis.baidu.com/fis3/docs/api/config-glob.html (selector规则)
//http://fis.baidu.com/fis3/docs/api/config-props.html (props属性说明)
fis.match(selector, props);
//例子 (排在后面的匹配会覆盖排在前面的匹配,类似于css样式)
fis.match('*.js', {
useHash: false
});
//fis.media() 接口提供多种状态功能,比如有些配置是仅供开发环境下使用,有些则是仅供生产环境使用的。
fis.media('prod').match('*.js', {
optimizer: fis.plugin('uglify-js')
});
//常用的功能组合
// 加 md5
fis.match('*.{js,css,png}', {
useHash: true
});
// 启用 fis-spriter-csssprites 插件
fis.match('::package', {
spriter: fis.plugin('csssprites')
});
// 对 CSS 进行图片合并
fis.match('*.css', {
// 给匹配到的文件分配属性 `useSprite`
useSprite: true
});
fis.match('*.js', {
// fis-optimizer-uglify-js 插件进行压缩,已内置
optimizer: fis.plugin('uglify-js')
});
fis.match('*.css', {
// fis-optimizer-clean-css 插件进行压缩,已内置
optimizer: fis.plugin('clean-css')
});
fis.match('*.png', {
// fis-optimizer-png-compressor 插件进行压缩,已内置
optimizer: fis.plugin('png-compressor')
});
//开发中的配置应为
fis.media('debug').match('*.{js,css,png}', {
useHash: false,
useSprite: false,
optimizer: null
})
fis3.medie('prod').match('*.{js,css,png}', {
useHash: true
}).match('*.js', {
optimizer: fis.plugin('uglify-js')
}).match('*.css', {
optimizer: fis.plugin('clean-css')
}).match('*.png', {
optimizer: fis.plugin('png-compressor')
}).match('::package', {
postpackager: fis.plugin('loader', {
allInOne: true
})
}).match('::package', {
spriter: fis.plugin('csssprites')
})
前端编译器的核心功能
- 资源定位:获取任何开发中所使用资源的线上路径;(可以调整资源的输出路径、引入路径等,详细看http://fis.baidu.com/fis3/docs/user-dev/uri.html)
- 内容嵌入:把一个文件的内容(文本)或者 base64 编码(图片)嵌入到另一个文件中;(对html、css、js使用__inline操作)
- 声明依赖:在一个文本文件内标记对其他资源的依赖关系;
fis3-postpackager-loader和fis3-hook-amd
使用以上插件进行fis3的模块化开发,前者用于依赖组件的加载,后者用于为依赖进行配置声明(类似于require.config)。此fis3模块化开发需要搭配require.js进行。