参考:
官方文档API
Javascript模块化编程(三):require.js的用法
JS模块化工具requirejs教程(一):初识requirej
RequireJS是一个非常小巧的JavaScript模块载入框架,是AMD规范最好的实现者之一

1 基本API

require会定义三个变量:define,require,requirejs,其中require === requirejs,一般使用require更简短

  • define 从名字就可以看出这个api是用来定义一个模块
  • require 加载依赖模块,并执行加载完后的回调函数

    1.1 define

    定义一个模块是通过 define (name, deps, callback)完成的,第一个参数是定义模块名,第二个参数是传入定义模块所需要的依赖,第三个函数则是定义模块的主函数,主函数和require的回调函数一样,同样是在依赖加载完以后再调用执行。

    1.1.1 当没有任何依赖的时候可以按照下面的来写

    1. define(function(){
    2. return{
    3. decs : 'this js will be request only if it is needed',
    4. };
    5. })

    1.1.2 当有相关依赖时可以按下面的来写

    1. define(['jquery'],function($){
    2. return function (){
    3. alert('asas');
    4. };
    5. })

    1.1.3 为什么我始终都没有使用name来定义自己的模块名

    如果你细心,你可能会发现,刚刚define函数,有一个参数name是用来定义模块名的(也就是第一个传参),为什么上面两个例子都没有用到。其实我确实可以添加模块名,如下:
    1. define(['jquery'],function($){
    2. return function (){
    3. alert('asas');
    4. };
    5. })
    但是,这样做感觉不很有必要,因为如果哪一天我将这个文件转移到其他目录下,那我就得在这这里再修改一次模块名。官方其实也不推荐,用官方的说法是:让优化工具去自动生成这些模块名吧
    image.png

    1.2 require


    1.2.1 加载依赖模块,并执行加载完后的回调函

    1. require(["js/a"],function(){
    2. alert("load finished");
    3. })
    ``` // main.js

  require([‘moduleA’, ‘moduleB’, ‘moduleC’], function (moduleA, moduleB, moduleC){

    // some code here

  });

  1. require()函数接受两个参数。第一个参数是一个数组,表示所依赖的模块,上例就是['moduleA', 'moduleB', 'moduleC'],即主模块依赖这三个模块;第二个参数是一个回调函数,当前面指定的模块都加载成功后,它将被调用。加载的模块会以参数形式传入该函数,从而在回调函数内部就可以使用这些模块。 require()异步加载moduleAmoduleBmoduleC,浏览器不会失去响应;它指定的回调函数,只有前面的模块 都加载成功后,才会运行,解决了依赖性的问题。<br />![image.png](https://cdn.nlark.com/yuque/0/2020/png/102566/1596610357879-f4b5f0e6-c5ed-49a8-b3e2-ff4aa53e7784.png#align=left&display=inline&height=262&margin=%5Bobject%20Object%5D&name=image.png&originHeight=524&originWidth=1758&size=92232&status=done&style=none&width=879)
  2. <a name="3M9U2"></a>
  3. #### <br />1.2.2 require.config
  4. 上面的例子,默认情况下,require.js假定这三个模块与main.js在同一个目录,文件名分别为jquery.jsunderscore.jsbackbone.js,然后自动加载。
  5. 实际情况,可能不是在同一目录,或者从网络获取
  6. 使用require.config()方法,我们可以对模块的加载行为进行自定义。require.config()就写在主模块(main.js)的头部。参数就是一个对象,这个对象的paths属性指定各个模块的加载路径。

require.config({     paths: {       “jquery”: “jquery.min”,       “underscore”: “underscore.min”,       “backbone”: “backbone.min”     } });

  1. ```
  2. require.config({
  3.     paths: {
  4.       "jquery": "lib/jquery.min",
  5.       "underscore": "lib/underscore.min",
  6.       "backbone": "lib/backbone.min"
  7.     }
  8.   });
  1.  require.config({
  2.     baseUrl: "js/lib",
  3.     paths: {
  4.       "jquery": "jquery.min",
  5.       "underscore": "underscore.min",
  6.       "backbone": "backbone.min"
  7.     }
  8.   });
  1. require.config({
  2.     paths: {
  3.       "jquery": "https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min"
  4.     }
  5.   });

同时,有些工具库也可能不符合AMD,需要提前配置
image.png

2 实际案列

2.1 编写模块代码

index.js

  1. /**
  2. * 1、模块路径配置
  3. * 2、配置不兼容模块
  4. **/
  5. requirejs.config({
  6. baseUrl: '//js.xxx.com/multi/src/',
  7. urlArgs:"342342",
  8. paths: {
  9. lib: 'common/base',
  10. tools: 'common/tools',
  11. ui: 'common/ui',
  12. tpl: 'common/tpl',
  13. header: 'common/header',
  14. lang: 'common/lang'
  15. },
  16. shim: {
  17. 'lib/backbone': {
  18. deps: ['lib/underscore', 'lib/jquery'],
  19. exports: 'Backbone'
  20. },
  21. 'lib/underscore': {
  22. exports: '_'
  23. },
  24. 'lib/jquery': {
  25. exports: '$'
  26. },
  27. 'tools/jquery.cookie': {
  28. deps: ['lib/jquery'],
  29. exports: '$cookie'
  30. }
  31. }
  32. });
  33. //调用入口文件
  34. requirejs(['competitor/main']);

main.js

  1. define(
  2. 'competitor/main',
  3. [
  4. 'common/config',
  5. 'common/langLoader',
  6. 'common/feedback',
  7. 'common/googletranslate',
  8. 'tools/jquery.cookie',
  9. 'competitor/uploader' ],
  10. function(
  11. CONFIG,
  12. langLoader,
  13. feedback,
  14. translate,
  15. JCookie,
  16. Uploader
  17. ){
  18. console.log(1)
  19. new Uploader()
  20. });

2.2 页面引入

页面引入requirejs和使用requirejs开发的项目
image.png

2.3 加载模块代码

requriejs会判断依赖是否存在,不存在则会去请求,就是在头部动态加入script标签

image.png

image.png
image.png
可以发现,每个依赖的js模块文件,requirejs都会去获取
image.png
只有依赖都下载后才会执行模块内代码。

2.4 生产环境-合并代码

使用 RequireJS 可以将我们的 JavaScript 代码轻易的分割成苦干个模块(module),方便我们的开发与维护。但是在生产环境中,如果将所有的 JavaScript 文件分离,会导致很多次请求(requests),即使这个些文件都很小,也会浪费很多时间。
所以在生产环境中,我们可以通过合并这些脚本文件,以减少请求的次数达到节省加载时间的目的。

RequireJS 提供了一个打包压缩工具 r.js,它是一个能运行基于 AMD 的项目的命令行工具,可以用来实现对模块的合并压缩。

也可以配合其他构件工具,如gulp、grunt等等。

还有其他合并代码的方式,见过使用php写一个合并文件的方法,配合wamp或nginx,在本地搭建一套开发环境,达到合并代码的目的。