Isa*_*aac 7 javascript amd requirejs
我正在开发一个JavaScript重的Web应用程序; 如果没有JavaScript,整个应用程序都是无用的.我目前正在使用requirejs作为我的模块加载器,以及将r.js我的JS优化为生产中的单个文件的工具.
目前,在生产中我的标记看起来像这样;
<script src="/js/require.js"></script>
<script>
require.config({
// blah blah blah
});
require(['editor']); // Bootstrap the JavaScript code.
</script>
Run Code Online (Sandbox Code Playgroud)
但是,这会异步加载JavaScript,这会使页面呈现尽管在加载JavaScript之前无法使用; 我没有看到这一点.相反,我想像这样同步加载JavaScript ;
<script src="/js/bundle.js"></script><!-- combine require.js, config and editor.js -->
Run Code Online (Sandbox Code Playgroud)
这样,当呈现页面时,它是可用的.我已经读过所有现代浏览器都支持并行加载,这使我相信互联网上的大多数建议都建议避免这种方法,因为它阻止并行下载已经过时了.
然而;
在开发中,我想将未组合的文件作为多个脚本标签插入,而不是单个缩小的文件;
<script src="/js/require.js"></script>
<script>/* require.config(...); */</script>
<script src="/js/editor-dep-1.js"></script>
<script src="/js/editor-dep-2.js"></script>
<script src="/js/editor.js"></script>
Run Code Online (Sandbox Code Playgroud)
...但是这在requirejs中显得非常繁琐(使用r.js生成虚假构建,获取依赖项的列表editor.js),感觉不对.
因此,我的问题如下;
<script />建议过时?我决定采纳ljfranklin 的建议,完全废除 RequireJS。我个人认为 AMD 做的都是错误的,CommonJS(及其同步行为)是正确的选择;但这是另一个讨论的事了。
\n\n我看到的一件事是转向Browserify,但在开发过程中,每次编译(因为它扫描所有文件并查找require()调用)花费的时间太长,我认为无法接受。
最后,我推出了自己的定制解决方案。它是它基本上Browserify,但它要求您指定所有依赖项,而不是让 Browserify 自行解决。这意味着编译只需几秒而不是 30 秒。
\n\n这就是 TL;DR。下面我就详细说说我是如何做到的。抱歉长度。希望这可以帮助某人......或者至少给某人一些启发!
\n\n首先,我有我的 JavaScript 文件。它们被写成 \xc3\xa0 la CommonJS,其限制是exports不能作为“全局”变量使用(你必须使用module.exports)。例如:
var anotherModule = require(\'./another-module\');\n\nmodule.exports.foo = function () {\n console.log(anotherModule.saySomething());\n};\nRun Code Online (Sandbox Code Playgroud)\n\n然后,我在配置文件中指定依赖项的有序列表(注意js/support.js,它会在稍后保存):
{\n "js": [\n "js/support.js",\n "js/jquery.js",\n "js/jquery-ui.js",\n "js/handlebars.js",\n // ...\n "js/editor/manager.js",\n "js/editor.js"\n ]\n}\nRun Code Online (Sandbox Code Playgroud)\n\n然后,在编译过程中,我映射了所有 JavaScript 文件(在js/目录中)映射到表单;
define(\'/path/to/js_file.js\', function (require, module) {\n // The contents of the JavaScript file\n});\nRun Code Online (Sandbox Code Playgroud)\n\n但这对于原始 JavaScript 文件来说是完全透明的;define下面我们提供了对、require等的所有支持module,这样,对于原始的 JavaScript 文件它就可以工作。
我使用 grunt 进行映射;首先将文件复制到build目录中(这样我就不会弄乱原始文件),然后重写文件。
// files were previous in public/js/*, move to build/js/*\ngrunt.initConfig({\n copy: {\n dist: {\n files: [{\n expand: true,\n cwd: \'public\',\n src: \'**/*\',\n dest: \'build/\'\n }]\n }\n }\n});\n\ngrunt.loadNpmTasks(\'grunt-contrib-copy\');\n\ngrunt.registerTask(\'buildjs\', function () {\n var path = require(\'path\');\n\n grunt.file.expand(\'build/**/*.js\').forEach(function (file) {\n grunt.file.copy(file, file, {\n process: function (contents, folder) {\n return \'define(\\\'\' + folder + \'\\\', function (require, module) {\\n\' + contents + \'\\n});\'\n },\n noProcess: \'build/js/support.js\'\n });\n });\n});\nRun Code Online (Sandbox Code Playgroud)\n\n我有一个 file /js/support.js,它定义了define()我包装每个文件的函数;这就是神奇发生的地方,因为它增加了对module.exports和 的支持require()在不到 40 行的时间内
(function () {\n var cache = {};\n\n this.define = function (path, func) {\n func(function (module) {\n var other = module.split(\'/\');\n var curr = path.split(\'/\');\n var target;\n\n other.push(other.pop() + \'.js\');\n curr.pop();\n\n while (other.length) {\n var next = other.shift();\n\n switch (next) {\n case \'.\':\n break;\n case \'..\':\n curr.pop();\n break;\n default:\n curr.push(next);\n }\n }\n\n target = curr.join(\'/\');\n\n if (!cache[target]) {\n throw new Error(target + \' required by \' + path + \' before it is defined.\');\n } else {\n return cache[target].exports;\n }\n }, cache[path] = {\n exports: {}\n });\n };\n}.call(this));\nRun Code Online (Sandbox Code Playgroud)\n\n然后,在开发过程中,我逐字迭代配置文件中的每个文件并将其输出为单独的文件<script />标签;一切都是同步的,没有任何事情被缩小,一切都很快。
{{#iter scripts}}<script src="{{this}}"></script>\n{{/iter}}\nRun Code Online (Sandbox Code Playgroud)\n\n这给了我;
\n\n<script src="js/support.js"></script>\n<script src="js/jquery.js"></script>\n<script src="js/jquery-ui.js"></script>\n<script src="js/handlebars.js"></script>\n<!-- ... -->\n<script src="js/editor/manager.js"></script>\n<script src="js/editor.js"></script>\nRun Code Online (Sandbox Code Playgroud)\n\n在生产中,我使用UglifyJs缩小并组合 JS 文件。好吧,从技术上讲,我使用 UglifyJs 的包装器;小型消防车。
\n\ngrunt.registerTask(\'compilejs\', function () {\n var minifier = require(\'mini-fier\').create();\n\n if (config.production) {\n var async = this.async();\n var files = bundles.js || [];\n\n minifier.js({\n srcPath: __dirname + \'/build/\',\n filesIn: files,\n destination: __dirname + \'/build/js/all.js\'\n }).on(\'error\', function () {\n console.log(arguments);\n async(false);\n }).on(\'complete\', function () {\n async();\n });\n }\n});\nRun Code Online (Sandbox Code Playgroud)\n\n...然后在应用程序代码中,我将scripts(用于容纳要在视图中输出的脚本的变量)更改为[\'/build/js/all.js\'],而不是实际文件的数组。这给了我一个
<script src="/js/all.js"></script> \nRun Code Online (Sandbox Code Playgroud)\n\n... 输出。同步、精简、相当快。
\n