私はljfranklin のアドバイスを受けて、RequireJS を完全に廃止することにしました。個人的には、AMD のやり方はすべて間違っていると思います。CommonJS (同期動作を伴う) が進むべき道です。しかし、それは別の議論のためです。
私が調べたことの 1 つは、Browserifyへの移行ですが、開発中の各コンパイル (すべてのファイルをスキャンしてrequire()
呼び出しを追跡するため) に時間がかかりすぎて、受け入れられるとは思えませんでした。
最終的に、私は独自のオーダーメイドのソリューションを展開しました。基本的には Browserify ですが、代わりに、Browserify にそれ自体を理解させるのではなく、すべての依存関係を指定する必要があります。これは、コンパイルが 30 秒ではなく、ほんの数秒であることを意味します。
それが TL;DRです。以下に、私がそれをどのように行ったかについて詳しく説明します。長々とすみません。これが誰かの役に立てば幸いです...または少なくとも誰かにインスピレーションを与えてください!
まず、JavaScript ファイルがあります。これらは CommonJS 風に書かれてexports
おり、「グローバル」変数として使用できないという制限があります (module.exports
代わりに使用する必要があります)。例えば:
var anotherModule = require('./another-module');
module.exports.foo = function () {
console.log(anotherModule.saySomething());
};
次に、構成ファイルで依存関係の順序どおりのリストを指定します (注意js/support.js
してください。後で保存されます)。
{
"js": [
"js/support.js",
"js/jquery.js",
"js/jquery-ui.js",
"js/handlebars.js",
// ...
"js/editor/manager.js",
"js/editor.js"
]
}
次に、コンパイル プロセスで、(js/
ディレクトリ内の) すべての JavaScript ファイルをフォームにマップします。
define('/path/to/js_file.js', function (require, module) {
// The contents of the JavaScript file
});
ただし、これは元の JavaScript ファイルに対して完全に透過的です。define
以下では、require
などのすべてのサポートを提供しているためmodule
、元の JavaScript ファイルに対しては.
私はうなり声を使用してマッピングを行います。最初にファイルをディレクトリにコピーしbuild
(オリジナルをいじらないように)、次にファイルを書き換えます。
// files were previous in public/js/*, move to build/js/*
grunt.initConfig({
copy: {
dist: {
files: [{
expand: true,
cwd: 'public',
src: '**/*',
dest: 'build/'
}]
}
}
});
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.registerTask('buildjs', function () {
var path = require('path');
grunt.file.expand('build/**/*.js').forEach(function (file) {
grunt.file.copy(file, file, {
process: function (contents, folder) {
return 'define(\'' + folder + '\', function (require, module) {\n' + contents + '\n});'
},
noProcess: 'build/js/support.js'
});
});
});
各ファイルをラップ/js/support.js
する関数を定義するfileがあります。40 行未満でandのdefine()
サポートが追加されるので、ここで魔法が起こります。module.exports
require()
(function () {
var cache = {};
this.define = function (path, func) {
func(function (module) {
var other = module.split('/');
var curr = path.split('/');
var target;
other.push(other.pop() + '.js');
curr.pop();
while (other.length) {
var next = other.shift();
switch (next) {
case '.':
break;
case '..':
curr.pop();
break;
default:
curr.push(next);
}
}
target = curr.join('/');
if (!cache[target]) {
throw new Error(target + ' required by ' + path + ' before it is defined.');
} else {
return cache[target].exports;
}
}, cache[path] = {
exports: {}
});
};
}.call(this));
次に、開発中に、構成ファイル内の各ファイルを文字通り繰り返し処理し、個別の<script />
タグとして出力します。すべてが同期し、縮小されたものはなく、すべてが迅速です。
{{#iter scripts}}<script src="{{this}}"></script>
{{/iter}}
これは私に与えます;
<script src="js/support.js"></script>
<script src="js/jquery.js"></script>
<script src="js/jquery-ui.js"></script>
<script src="js/handlebars.js"></script>
<!-- ... -->
<script src="js/editor/manager.js"></script>
<script src="js/editor.js"></script>
本番環境では、 UglifyJsを使用して JS ファイルを縮小および結合します。技術的には、UglifyJ のラッパーを使用します。ミニファイア。
grunt.registerTask('compilejs', function () {
var minifier = require('mini-fier').create();
if (config.production) {
var async = this.async();
var files = bundles.js || [];
minifier.js({
srcPath: __dirname + '/build/',
filesIn: files,
destination: __dirname + '/build/js/all.js'
}).on('error', function () {
console.log(arguments);
async(false);
}).on('complete', function () {
async();
});
}
});
... 次に、アプリケーション コードで、scripts
(ビューに出力するスクリプトを格納するために使用する変数) を、['/build/js/all.js']
実際のファイルの配列ではなく、単に に変更します。それは私にシングルを与えます
<script src="/js/all.js"></script>
...出力。同期、縮小、適度に高速。