84669 人學習
152542 人學習
20005 人學習
5487 人學習
7821 人學習
359900 人學習
3350 人學習
180660 人學習
48569 人學習
18603 人學習
40936 人學習
1549 人學習
1183 人學習
32909 人學習
AMD的框架比如requireJS和seaJS,项目不想引用。想自己写JS脚本来按需加载,并且处理好依赖关系,目前想到的方法是callback(利用script的onload事件来执行回调)
各位大神有没有其他比较优雅办法来实现按需加载?
拥有18年软件开发和IT教学经验。曾任多家上市公司技术总监、架构师、项目经理、高级软件工程师等职务。 网络人气名人讲师,...
其实按需加载不是很难,你只需要2个东西就能办到
一个模块加载器
一些符合模块加载器语法的代码
首先实现一个模块加载器其实并不复杂,不到50行就能办到,但是如果你想要一个功能完善的,可配置,具有完善的生态和社区的模块加载器。在几年前是requirejs和seajs,现在是browserify和webpack。webpack和browserify在模块加载方面相比requirejs和seajs更高级的地方是在node环境下自动进行依赖分析。
requirejs
seajs
browserify
webpack
让我们来实现个简单的兼容commonJS规范的模块加载器吧。
commonJS
(function (global) { var factoryMap = {}; var resMap = {}; var moduleMaps = {}; window.resMap = resMap; // define函数定义 define = function (id, factory) { factoryMap[id] = factory; } // require函数定义 require = function (id) { var mod = moduleMaps[id] = { exports: {} } var factory = factoryMap[id]; if (!factory) { throw 'Cannot find module `' + id + '`'; } var ret = factory.apply(mod, [require, mod.exports, mod]); if (ret) { mod.exports = ret; } return mod.exports; } })(this);
对于这样的模块加载器你就得这样来用。
// 模块1 依赖 模块二的内容 define('module1', function (require, exports, module) { // console.log(1); var module2 = require('module2'); var module3 = require('module3'); var module5 = require('module5'); var module6 = require('module6'); console.log('module1 --> module2', module2); console.log('module1 --> module3', module3); console.log('module1 --> module5', module5); console.log('module1 --> module6', module6); module.exports = { moduleName: 'module1' } }) // 模块二 依赖 模块三的内容 define('module2', function (require, exports, module) { var module6 = require('module6'); console.log('module2 --> module6', module6); module.exports = { moduleName: 'module2' } }) // 模块三 define('module3', function (require, exports, module) { // console.log('3'); var module4 = require('module4'); var module5 = require('module5'); var module2 = require('module2'); console.log('module3 --> module5', module5); console.log('module3 --> module2', module2); console.log('module3 --> module4', module4); module.exports = { moduleName: 'module3' } }) define('module4', function (require, exports, module) { var module6 = require('module6'); console.log('module4 --> module6', module6); module.exports = { moduleName: 'module4' } }); define('module5', function (require, exports, module) { var module2 = require('module2'); var module6 = require('module6'); console.log('module5 --> module2', module2); console.log('module5 --> module6', module6); module.exports = { moduleName: 'module5' } }) define('module6', function (require, exports, module) { module.exports = { moduleName: 'module6' } }) require('module1');
大家可以把所有代码放到浏览器里面实验一下。。。
下面说些有关模块加载器的题外话。有兴趣的可以继续往下读。。
如果大家很好奇webpack的产出的话,也会发现webpack产出的bundle的最顶部带有的模块加载器也类似于上面的代码。
但是我们的代码相比browserify,相比requirejs或者seajs一定还少些什么。
一个模块的依赖必须等到运行的时候才知道,如果缺乏相关模块的定义,那就只能报错
无法自动加载需要的模块
没有依赖分析工具
在seajs和requirejs只实现了第一点和第二点。seajs会在运行define的callback函数之前从其源代码里面找出所有的require定义,比如
define
require
define('module1', function () { var $ = require('jquery') });
在执行define的时候,seajs已经知道了module1依赖jquery,然后就自动按照配置发送个http请求去下载定义为jquery的这个模块。
module1
jquery
对于requirejs来说,模块的依赖已经在代码中声明好了,只需要读到模块名称,然后根据配置生成路径去下载即可。
但是无论是requirejs还是seajs,它们都有一个致命弱点 ---- 一个模块的依赖竟然是开发者自己去写!!
在这个飞速发展,各个领域都朝向自动化的时代是远远不够的!
于是,Github上有个人搞了一个browserify。使用node来跑依赖分析,自动帮你把各个模块的依赖都搞定,从此只需要写require即可。
虽然用browserify确实爽,但是既然用了node来搞js的依赖分析,那还不如直接把所有的依赖分析都弄了算了。。。
于是这个时候,有2个团队做了这个事情。
FIS3
但是为啥FIS没流行下来,主要还是当时FIS搞出了这个功能,但是并没多少人知道,大家对FIS的印象还只停留在FIS2那个时代。。不过现在FIS3已经非常吊了。(原谅我的硬广告(。・`ω´・) )
不过webpack还是火了。
虽然webpack和fis都有代码依赖分析的功能,但是webpack依然和browserify一样,把所有的模块都打包在一个文件里(也是有方法分开的)。
fis
FIS是给每一个文件都包裹一个在文章最上面的给的那样
FIS
define('xxx', function () { // source code })
这样的语法,再手动引入一个mod.js ---简易模块加载器,并再入口的html里面自动生成一对script标签来实现模块加载。
mod.js
html
script
关键是这样复杂的功能竟然是分成了3个插件的,还要自己手动装!!!(能火才怪 - - )
不过FIS依然是青龙偃月刀一样的存在,大神拿来配好之后各种牛逼,前后端编译通吃。
webpack可以实现按需加载
可以使用ajax,比如jq里面的$.getScript()
$.getScript()
其实最好的建议就用现成的工具,如果非想自己写一个,思路参考下script吧,代码简单也清晰
自己实现也不难,主要思路就是有个config配置需要动态加载js库的path,然后在运行时,由你的加载器,动态的创 <script src='js_Path'/>标签,并把把它append到<head/>中。你的加载器能自适应市面上主流的几种规范即可,比如global var,AMD,Commonjs等。
其实按需加载不是很难,你只需要2个东西就能办到
一个模块加载器
一些符合模块加载器语法的代码
首先实现一个模块加载器其实并不复杂,不到50行就能办到,但是如果你想要一个功能完善的,可配置,具有完善的生态和社区的模块加载器。在几年前是
requirejs
和seajs
,现在是browserify
和webpack
。webpack
和browserify
在模块加载方面相比requirejs
和seajs
更高级的地方是在node环境下自动进行依赖分析。让我们来实现个简单的兼容
commonJS
规范的模块加载器吧。对于这样的模块加载器你就得这样来用。
大家可以把所有代码放到浏览器里面实验一下。。。
下面说些有关模块加载器的题外话。有兴趣的可以继续往下读。。
如果大家很好奇
webpack
的产出的话,也会发现webpack
产出的bundle的最顶部带有的模块加载器也类似于上面的代码。但是我们的代码相比
browserify
,相比requirejs
或者seajs
一定还少些什么。一个模块的依赖必须等到运行的时候才知道,如果缺乏相关模块的定义,那就只能报错
无法自动加载需要的模块
没有依赖分析工具
在
seajs
和requirejs
只实现了第一点和第二点。seajs
会在运行define
的callback函数之前从其源代码里面找出所有的require
定义,比如在执行
define
的时候,seajs
已经知道了module1
依赖jquery
,然后就自动按照配置发送个http请求去下载定义为jquery
的这个模块。对于
requirejs
来说,模块的依赖已经在代码中声明好了,只需要读到模块名称,然后根据配置生成路径去下载即可。但是无论是
requirejs
还是seajs
,它们都有一个致命弱点 ---- 一个模块的依赖竟然是开发者自己去写!!在这个飞速发展,各个领域都朝向自动化的时代是远远不够的!
于是,Github上有个人搞了一个browserify。
使用node来跑依赖分析,自动帮你把各个模块的依赖都搞定,从此只需要写require即可。
虽然用browserify确实爽,但是既然用了node来搞js的依赖分析,那还不如直接把所有的依赖分析都弄了算了。。。
于是这个时候,有2个团队做了这个事情。
FIS3
webpack
但是为啥FIS没流行下来,主要还是当时FIS搞出了这个功能,但是并没多少人知道,大家对FIS的印象还只停留在FIS2那个时代。。不过现在FIS3已经非常吊了。(原谅我的硬广告(。・`ω´・) )
不过
webpack
还是火了。虽然
webpack
和fis
都有代码依赖分析的功能,但是webpack
依然和browserify
一样,把所有的模块都打包在一个文件里(也是有方法分开的)。FIS
是给每一个文件都包裹一个在文章最上面的给的那样这样的语法,再手动引入一个
mod.js
---简易模块加载器,并再入口的html
里面自动生成一对script
标签来实现模块加载。关键是这样复杂的功能竟然是分成了3个插件的,还要自己手动装!!!(能火才怪 - - )
不过FIS依然是青龙偃月刀一样的存在,大神拿来配好之后各种牛逼,前后端编译通吃。
webpack可以实现按需加载
可以使用ajax,比如jq里面的
$.getScript()
其实最好的建议就用现成的工具,如果非想自己写一个,思路参考下script吧,代码简单也清晰
自己实现也不难,主要思路就是有个config配置需要动态加载js库的path,然后在运行时,由你的加载器,动态的创 <script src='js_Path'/>标签,并把把它append到<head/>中。你的加载器能自适应市面上主流的几种规范即可,比如global var,AMD,Commonjs等。