84669 Lernen von Personen
152542 Lernen von Personen
20005 Lernen von Personen
5487 Lernen von Personen
7821 Lernen von Personen
359900 Lernen von Personen
3350 Lernen von Personen
180660 Lernen von Personen
48569 Lernen von Personen
18603 Lernen von Personen
40936 Lernen von Personen
1549 Lernen von Personen
1183 Lernen von Personen
32909 Lernen von Personen
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等。