源码构建

jQuery的代码是分模块书写的,最后通过一系列build的过程,才生产我们日常使用的版本。熟悉它的构建过程,有利于我们了解个各模块,以及组织的方式,便于我们后续自己开发。

前期准备

通过git更新下jquery的最新源码,进入对应的目录,执行npm install,确保本地安装过grunt,如果没有,执行npm install -g grunt-cli

jQuery组织方式

jQuery的源码是按照AMD的模式组织的,在构建的时候,去掉define结构,形成一个单独的文件。

构建步骤

执行grunt,默认会执行一系列任务,我们可以通过终端查看到其中的具体任务,我在这里再分条列一下:

  • Running "build:all:*" (build) task
  • Running "jsonlint:pkg" (jsonlint) task
  • Running "jsonlint:bower" (jsonlint) task
  • Running "jshint:all" (jshint) task
  • Running "jshint:dist" (jshint) task
  • Running "jscs:src" (jscs) task
  • Running "jscs:gruntfile" (jscs) task
  • Running "jscs:test" (jscs) task
  • Running "jscs:release" (jscs) task
  • Running "jscs:tasks" (jscs) task
  • Running "uglify:all" (uglify) task
  • Running "remove_map_comment" task
  • Running "dist:*" (dist) task
  • Running "node_smoke_test" task
  • Running "compare_size:files" (compare_size) task
    可以看到,构建任务确实不少。下面我们就依次来分析一下具体的任务负责了什么。具体的任务配置,我们需要查看gruntfile.js文件。

gruntfile.js文件

这是构建工具的入口,我们在这个文件的最后部分可以看到:

  1. // Load grunt tasks from NPM packages
  2. require( "load-grunt-tasks" )( grunt );
  3. // Integrate jQuery specific tasks
  4. grunt.loadTasks( "build/tasks" );
  5. grunt.registerTask( "lint", [ "jsonlint", "jshint", "jscs" ] );
  6. grunt.registerTask( "test_fast", [ "node_smoke_test" ] );
  7. grunt.registerTask( "test", [ "test_fast", "promises-aplus-tests" ] );
  8. // Short list as a high frequency watch task
  9. grunt.registerTask( "dev", [ "build:*:*", "lint", "uglify", "remove_map_comment", "dist:*" ] );
  10. grunt.registerTask( "default", [ "dev", "test_fast", "compare_size" ] );

这里注册了grunt的插件,以及默认的构建任务,比如我们将要看到的grunt其实,就是grunt default,是一系列任务的组合。这里还加载了build/tasks下的构建任务。

Running “build:all:*” (build) task

这个就是构建出开发版本的过程,我们先来看一下默认的build/task/build.js文件。这个文件确切定义了build任务,在文件的尾部,我们可以看到:

  1. // Trace dependencies and concatenate files
  2. requirejs.optimize( config, function( response ) {
  3. grunt.verbose.writeln( response );
  4. grunt.log.ok( "File '" + name + "' created." );
  5. done();
  6. }, function( err ) {
  7. done( err );
  8. });

这里通过requireJS的压缩,达到build的效果。主要的参数是通过config传入的,查看这个参数,我们会发现一个onBuildWrite选项,这会在构建的时候,帮我们执行去除define的效果,达到合并文件的目的。我们在convert中打印一下参数,可以查看到jQuery到底合并了哪些模块以及其对应的路径,默认情况下是依赖config下定义的src+name文件形成依赖关系:

  1. ====convert: var/arr /Users/leohxj/workspaces/github/jquery/src/var/arr.js
  2. ====convert: var/document /Users/leohxj/workspaces/github/jquery/src/var/document.js
  3. ====convert: var/slice /Users/leohxj/workspaces/github/jquery/src/var/slice.js
  4. ====convert: var/concat /Users/leohxj/workspaces/github/jquery/src/var/concat.js
  5. ====convert: var/push /Users/leohxj/workspaces/github/jquery/src/var/push.js
  6. ====convert: var/indexOf /Users/leohxj/workspaces/github/jquery/src/var/indexOf.js
  7. ====convert: var/class2type /Users/leohxj/workspaces/github/jquery/src/var/class2type.js
  8. ====convert: var/toString /Users/leohxj/workspaces/github/jquery/src/var/toString.js
  9. ====convert: var/hasOwn /Users/leohxj/workspaces/github/jquery/src/var/hasOwn.js
  10. ====convert: var/support /Users/leohxj/workspaces/github/jquery/src/var/support.js
  11. ====convert: core /Users/leohxj/workspaces/github/jquery/src/core.js
  12. ====convert: sizzle /Users/leohxj/workspaces/github/jquery/external/sizzle/dist/sizzle.js
  13. ====convert: selector-sizzle /Users/leohxj/workspaces/github/jquery/src/selector-sizzle.js
  14. ====convert: selector /Users/leohxj/workspaces/github/jquery/src/selector.js
  15. ====convert: traversing/var/rneedsContext /Users/leohxj/workspaces/github/jquery/src/traversing/var/rneedsContext.js
  16. ====convert: core/var/rsingleTag /Users/leohxj/workspaces/github/jquery/src/core/var/rsingleTag.js
  17. ====convert: traversing/findFilter /Users/leohxj/workspaces/github/jquery/src/traversing/findFilter.js
  18. ====convert: core/init /Users/leohxj/workspaces/github/jquery/src/core/init.js
  19. ====convert: traversing /Users/leohxj/workspaces/github/jquery/src/traversing.js
  20. ====convert: var/rnotwhite /Users/leohxj/workspaces/github/jquery/src/var/rnotwhite.js
  21. ====convert: callbacks /Users/leohxj/workspaces/github/jquery/src/callbacks.js
  22. ====convert: deferred /Users/leohxj/workspaces/github/jquery/src/deferred.js
  23. ====convert: core/ready /Users/leohxj/workspaces/github/jquery/src/core/ready.js
  24. ====convert: core/access /Users/leohxj/workspaces/github/jquery/src/core/access.js
  25. ====convert: data/accepts /Users/leohxj/workspaces/github/jquery/src/data/accepts.js
  26. ====convert: data/Data /Users/leohxj/workspaces/github/jquery/src/data/Data.js
  27. ====convert: data/var/dataPriv /Users/leohxj/workspaces/github/jquery/src/data/var/dataPriv.js
  28. ====convert: data/var/dataUser /Users/leohxj/workspaces/github/jquery/src/data/var/dataUser.js
  29. ====convert: data /Users/leohxj/workspaces/github/jquery/src/data.js
  30. ====convert: queue /Users/leohxj/workspaces/github/jquery/src/queue.js
  31. ====convert: var/pnum /Users/leohxj/workspaces/github/jquery/src/var/pnum.js
  32. ====convert: var/rcssNum /Users/leohxj/workspaces/github/jquery/src/var/rcssNum.js
  33. ====convert: css/var/cssExpand /Users/leohxj/workspaces/github/jquery/src/css/var/cssExpand.js
  34. ====convert: css/var/isHidden /Users/leohxj/workspaces/github/jquery/src/css/var/isHidden.js
  35. ====convert: css/adjustCSS /Users/leohxj/workspaces/github/jquery/src/css/adjustCSS.js
  36. ====convert: manipulation/var/rcheckableType /Users/leohxj/workspaces/github/jquery/src/manipulation/var/rcheckableType.js
  37. ====convert: manipulation/support /Users/leohxj/workspaces/github/jquery/src/manipulation/support.js
  38. ====convert: event/support /Users/leohxj/workspaces/github/jquery/src/event/support.js
  39. ====convert: event /Users/leohxj/workspaces/github/jquery/src/event.js
  40. ====convert: manipulation /Users/leohxj/workspaces/github/jquery/src/manipulation.js
  41. ====convert: css/defaultDisplay /Users/leohxj/workspaces/github/jquery/src/css/defaultDisplay.js
  42. ====convert: css/var/rmargin /Users/leohxj/workspaces/github/jquery/src/css/var/rmargin.js
  43. ====convert: css/var/rnumnonpx /Users/leohxj/workspaces/github/jquery/src/css/var/rnumnonpx.js
  44. ====convert: css/var/getStyles /Users/leohxj/workspaces/github/jquery/src/css/var/getStyles.js
  45. ====convert: var/documentElement /Users/leohxj/workspaces/github/jquery/src/var/documentElement.js
  46. ====convert: css/support /Users/leohxj/workspaces/github/jquery/src/css/support.js
  47. ====convert: css/curCSS /Users/leohxj/workspaces/github/jquery/src/css/curCSS.js
  48. ====convert: css/addGetHookIf /Users/leohxj/workspaces/github/jquery/src/css/addGetHookIf.js
  49. ====convert: css/swap /Users/leohxj/workspaces/github/jquery/src/css/swap.js
  50. ====convert: css /Users/leohxj/workspaces/github/jquery/src/css.js
  51. ====convert: effects/Tween /Users/leohxj/workspaces/github/jquery/src/effects/Tween.js
  52. ====convert: effects /Users/leohxj/workspaces/github/jquery/src/effects.js
  53. ====convert: queue/delay /Users/leohxj/workspaces/github/jquery/src/queue/delay.js
  54. ====convert: attributes/support /Users/leohxj/workspaces/github/jquery/src/attributes/support.js
  55. ====convert: attributes/attr /Users/leohxj/workspaces/github/jquery/src/attributes/attr.js
  56. ====convert: attributes/prop /Users/leohxj/workspaces/github/jquery/src/attributes/prop.js
  57. ====convert: attributes/classes /Users/leohxj/workspaces/github/jquery/src/attributes/classes.js
  58. ====convert: attributes/val /Users/leohxj/workspaces/github/jquery/src/attributes/val.js
  59. ====convert: attributes /Users/leohxj/workspaces/github/jquery/src/attributes.js
  60. ====convert: event/alias /Users/leohxj/workspaces/github/jquery/src/event/alias.js
  61. ====convert: ajax/var/location /Users/leohxj/workspaces/github/jquery/src/ajax/var/location.js
  62. ====convert: ajax/var/nonce /Users/leohxj/workspaces/github/jquery/src/ajax/var/nonce.js
  63. ====convert: ajax/var/rquery /Users/leohxj/workspaces/github/jquery/src/ajax/var/rquery.js
  64. ====convert: ajax/parseJSON /Users/leohxj/workspaces/github/jquery/src/ajax/parseJSON.js
  65. ====convert: ajax/parseXML /Users/leohxj/workspaces/github/jquery/src/ajax/parseXML.js
  66. ====convert: ajax /Users/leohxj/workspaces/github/jquery/src/ajax.js
  67. ====convert: manipulation/_evalUrl /Users/leohxj/workspaces/github/jquery/src/manipulation/_evalUrl.js
  68. ====convert: wrap /Users/leohxj/workspaces/github/jquery/src/wrap.js
  69. ====convert: css/hiddenVisibleSelectors /Users/leohxj/workspaces/github/jquery/src/css/hiddenVisibleSelectors.js
  70. ====convert: serialize /Users/leohxj/workspaces/github/jquery/src/serialize.js
  71. ====convert: ajax/xhr /Users/leohxj/workspaces/github/jquery/src/ajax/xhr.js
  72. ====convert: ajax/script /Users/leohxj/workspaces/github/jquery/src/ajax/script.js
  73. ====convert: ajax/jsonp /Users/leohxj/workspaces/github/jquery/src/ajax/jsonp.js
  74. ====convert: core/support /Users/leohxj/workspaces/github/jquery/src/core/support.js
  75. ====convert: core/parseHTML /Users/leohxj/workspaces/github/jquery/src/core/parseHTML.js
  76. ====convert: ajax/load /Users/leohxj/workspaces/github/jquery/src/ajax/load.js
  77. ====convert: event/ajax /Users/leohxj/workspaces/github/jquery/src/event/ajax.js
  78. ====convert: effects/animatedSelector /Users/leohxj/workspaces/github/jquery/src/effects/animatedSelector.js
  79. ====convert: offset /Users/leohxj/workspaces/github/jquery/src/offset.js
  80. ====convert: dimensions /Users/leohxj/workspaces/github/jquery/src/dimensions.js
  81. ====convert: deprecated /Users/leohxj/workspaces/github/jquery/src/deprecated.js
  82. ====convert: exports/amd /Users/leohxj/workspaces/github/jquery/src/exports/amd.js
  83. ====convert: jquery /Users/leohxj/workspaces/github/jquery/src/jquery.js

我们也可以指定构建模块,比如使用grunt build:*:core:selector,来确定构建coreselector模块:

  1. ====convert: jquery /Users/leohxj/workspaces/github/jquery/src/jquery.js
  2. ====convert: var/arr /Users/leohxj/workspaces/github/jquery/src/var/arr.js
  3. ====convert: var/document /Users/leohxj/workspaces/github/jquery/src/var/document.js
  4. ====convert: var/slice /Users/leohxj/workspaces/github/jquery/src/var/slice.js
  5. ====convert: var/concat /Users/leohxj/workspaces/github/jquery/src/var/concat.js
  6. ====convert: var/push /Users/leohxj/workspaces/github/jquery/src/var/push.js
  7. ====convert: var/indexOf /Users/leohxj/workspaces/github/jquery/src/var/indexOf.js
  8. ====convert: var/class2type /Users/leohxj/workspaces/github/jquery/src/var/class2type.js
  9. ====convert: var/toString /Users/leohxj/workspaces/github/jquery/src/var/toString.js
  10. ====convert: var/hasOwn /Users/leohxj/workspaces/github/jquery/src/var/hasOwn.js
  11. ====convert: var/support /Users/leohxj/workspaces/github/jquery/src/var/support.js
  12. ====convert: core /Users/leohxj/workspaces/github/jquery/src/core.js
  13. ====convert: sizzle /Users/leohxj/workspaces/github/jquery/external/sizzle/dist/sizzle.js
  14. ====convert: selector-sizzle /Users/leohxj/workspaces/github/jquery/src/selector-sizzle.js
  15. ====convert: selector /Users/leohxj/workspaces/github/jquery/src/selector.js

参考资料

原文: https://leohxj.gitbooks.io/front-end-database/content/jQuery/jQuery-source-code/code-build.html