RequireJS целая папка
Возможно ли "потребовать" целую папку с помощью requireJS.
Например, у меня есть папка поведения с тонны js файлов поведения. Я действительно хотел бы иметь возможность просто использовать require (['behaviors/*'], function() {...}); загрузить все в эту папку, а не обновлять этот список. После сжатия и оптимизации у меня были бы все эти файлы вместе, но для разработки проще работать с ними по отдельности.
Ответы
Ответ 1
javascript в браузере не имеет доступа к файловой системе и поэтому не может сканировать каталог для файлов. Если вы создаете свое приложение на языке сценариев, например php или ruby, вы можете написать script, который сканирует каталог и добавляет имена файлов в вызов require().
Ответ 2
Пока JavaScript в браузере не может (и не должен) видеть файловую систему, я создал задачу Grunt, которая будет делать именно это. Я в настоящее время все еще работаю над этим, касаясь его здесь и там, но вы можете взглянуть.
https://npmjs.org/package/require-wild
npm install require-wild
В вашем случае все, что вам нужно сделать, это настроить параметры задачи
grunt.initConfig({
requireWild: {
app: {
// Input files to look for wildcards (require|define)
src: ["./**/*.js"],
// Output file contains generated namespace modules
dest: "./namespaces.js",
// Load your require config file used to find baseUrl - optional
options: { requireConfigFile: "./main.js" }
}
}
});
grunt.loadNpmTasks("require-wild");
grunt.registerTask('default', ['requireWild']);
Затем запустите задачу grunt. Ваш файл будет сгенерирован. Измените свой main.js
, чтобы загрузить namespaces.js
require(['namespaces'], function () { ... });
Таким образом, теперь позволяет модулям под src
использовать зависимости с сопоставлением шаблонов glunt glob.
require(['behaviors/**/*'], function (behaviors) { }
Эта идеология предполагает, что у вас есть значимая файловая структура.
Ответ 3
Я знаю, что это устарело, но я хочу поделиться своим решением:
Для этого решения вам нужен JQuery
1) Создайте bash script, который будет отображать все js файлы в "MyDirectory/" и сохраните его в "directoryContents.txt" :
#!/bin/bash
#Find all the files in that directory...
for file in $( find MyDirectory/ -type f -name "*.js" )
do
fileClean=${file%.js} #Must remove .js from the end!
echo -n "$fileClean " >> MyDirectory/directoryContents.txt
done
- Файл будет выглядеть следующим образом:
MyDirectory/FirstJavascriptFile MyDirectory/SecondJavascriptFile MyDirectory/ThirdJavascriptFile
- Проблема с моим script! В конце добавляет лишний ", это все испортит! Убедитесь, что удалить лишнее пространство в конце directoryContents.txt
2) Затем на вашем клиентском JS-коде:
- выполнить запрос "GET" для получения текстового файла
- Для каждой записи (разделенной пробелом) требуется "файл":
.
$.get( "MyDirectory/directoryContents.txt", {}, function( data ) {
var allJsFilesInFolder = data.split(" ");
for(var a=0; a<allJsFilesInFolder.length; a++)
{
require([allJsFilesInFolder[a]], function(jsConfig)
{
//Done loading this one file
});
}
}, "text");
У меня возникла проблема с тем, что этот код не заканчивается до моего другого кода, так что мой расширенный ответ:
define([''], function() {
return {
createTestMenu: function()
{
this.loadAllJSFiles(function(){
//Here ALL those files you need are loaded!
});
},
loadAllJSFiles: function(callback)
{
$.get( "MyDirectory/directoryContents.txt", {}, function( data ) {
var allJsFilesInFolder = data.split(" ");
var currentFileNum = 0;
for(var a=0; a<allJsFilesInFolder.length; a++)
{
require([allJsFilesInFolder[a]], function(jsConfig)
{
currentFileNum++;
//If it the last file that needs to be loaded, run the callback.
if (currentFileNum==allJsFilesInFolder.length)
{
console.log("Done loading all configuration files.");
if (typeof callback != "undefined"){callback();}
}
});
}
}, "text");
}
}
});
То, что я закончил, было каждый раз, когда мой сервер Node загружался, он запускает bash script, заполняющий directoryContents.txt. Затем моя клиентская сторона просто считывает каталогContents.txt для списка файлов и требует каждого в этом списке.
Надеюсь, это поможет!
Ответ 4
На самом деле нет способа сделать это концептуально "на лету" (что я знаю).
Там немного работы:
Используйте grunt
и concat
, а затем просто требуйте этого бегемота... Я знаю, вроде бы сосать.
Я думаю, что это лучшее решение... используйте иерархию требуемого типа:
require('/js/controllers/init', function(ctrls){
ctrls(app, globals);
});
// /js/controllers/init.js
define('js/controllers/index', 'js/controllers/posts', function(index, posts){
return function protagonist(app, globals){
var indexModule = index(app, globals);
var indexModule = posts(app, globals);
return app || someModule;
};
});
// /js/controllers/index.js
define('js/controllers/index', 'js/controllers/posts', function(index, posts){
return function protagonist(app, globals){
function method1(){}
function method2(){}
return {
m1: method1,
m2: method2
};
};
});
Обратите внимание, что "protagonist
" function
. Это позволяет вам инициализировать модули до их использования, поэтому теперь вы можете перейти в "sandbox
" - в этом случае app
и globals
.
Реально, у вас не было бы /js/controllers/index.js
... Вероятно, это должно быть что-то вроде /js/controllers/index/main.js
или /js/controllers/index/init.js
, так что есть каталог, смежный с (sibling of) /js/controllers/init.js
, называемый "index". Это сделает ваши модули масштабируемыми для данного интерфейса - вы можете просто заменить модули и сохранить свой интерфейс одинаково.
Надеюсь, это поможет! Счастливое кодирование!
Ответ 5
Я написал библиотеку для решения этой проблемы.
Вы можете использовать мой lib с Gulp или что угодно - он генерирует метаданные для вашего проекта, а RequireJS может использовать эти метаданные, чтобы потребовать нужные файлы из файловой системы.
С помощью этого lib будет создан модуль RequireJS, который выглядит примерно так:
define(
[
"text!app/templates/dashboardTemplate.ejs",
"text!app/templates/fluxCartTemplate.ejs",
"text!app/templates/footerTemplate.ejs",
"text!app/templates/getAllTemplate.ejs",
"text!app/templates/headerTemplate.ejs",
"text!app/templates/homeTemplate.ejs",
"text!app/templates/indexTemplate.ejs",
"text!app/templates/jobsTemplate.ejs",
"text!app/templates/loginTemplate.ejs",
"text!app/templates/overviewTemplate.ejs",
"text!app/templates/pictureTemplate.ejs",
"text!app/templates/portalTemplate.ejs",
"text!app/templates/registeredUsersTemplate.ejs",
"text!app/templates/userProfileTemplate.ejs"
],
function(){
return {
"templates/dashboardTemplate.ejs": arguments[0],
"templates/fluxCartTemplate.ejs": arguments[1],
"templates/footerTemplate.ejs": arguments[2],
"templates/getAllTemplate.ejs": arguments[3],
"templates/headerTemplate.ejs": arguments[4],
"templates/homeTemplate.ejs": arguments[5],
"templates/indexTemplate.ejs": arguments[6],
"templates/jobsTemplate.ejs": arguments[7],
"templates/loginTemplate.ejs": arguments[8],
"templates/overviewTemplate.ejs": arguments[9],
"templates/pictureTemplate.ejs": arguments[10],
"templates/portalTemplate.ejs": arguments[11],
"templates/registeredUsersTemplate.ejs": arguments[12],
"templates/userProfileTemplate.ejs": arguments[13]
}
});
и еще больший пример:
define(
[
"app/js/jsx/BaseView",
"app/js/jsx/GenericView",
"app/js/jsx/controllerViews/FluxCartApp",
"app/js/jsx/reactComponents/FluxCart",
"app/js/jsx/reactComponents/FluxProduct",
"app/js/jsx/reactComponents/Item",
"app/js/jsx/reactComponents/Job",
"app/js/jsx/reactComponents/JobsList",
"app/js/jsx/reactComponents/MenuExample",
"app/js/jsx/reactComponents/Picture",
"app/js/jsx/reactComponents/PictureList",
"app/js/jsx/reactComponents/RealTimeSearchView",
"app/js/jsx/reactComponents/Service",
"app/js/jsx/reactComponents/ServiceChooser",
"app/js/jsx/reactComponents/TimerExample",
"app/js/jsx/reactComponents/listView",
"app/js/jsx/reactComponents/todoList",
"app/js/jsx/relViews/FluxCart/FluxCartMain",
"app/js/jsx/relViews/getAll/getAll",
"app/js/jsx/relViews/jobs/jobsView",
"app/js/jsx/standardViews/IndexView",
"app/js/jsx/standardViews/dashboardView",
"app/js/jsx/standardViews/footerView",
"app/js/jsx/standardViews/headerView",
"app/js/jsx/standardViews/homeView",
"app/js/jsx/standardViews/loginView",
"app/js/jsx/standardViews/overviewView",
"app/js/jsx/standardViews/pictureView",
"app/js/jsx/standardViews/portalView",
"app/js/jsx/standardViews/registeredUsersView",
"app/js/jsx/standardViews/userProfileView"
],
function(){
return {
"BaseView": arguments[0],
"GenericView": arguments[1],
"controllerViews/FluxCartApp": arguments[2],
"reactComponents/FluxCart": arguments[3],
"reactComponents/FluxProduct": arguments[4],
"reactComponents/Item": arguments[5],
"reactComponents/Job": arguments[6],
"reactComponents/JobsList": arguments[7],
"reactComponents/MenuExample": arguments[8],
"reactComponents/Picture": arguments[9],
"reactComponents/PictureList": arguments[10],
"reactComponents/RealTimeSearchView": arguments[11],
"reactComponents/Service": arguments[12],
"reactComponents/ServiceChooser": arguments[13],
"reactComponents/TimerExample": arguments[14],
"reactComponents/listView": arguments[15],
"reactComponents/todoList": arguments[16],
"relViews/FluxCart/FluxCartMain": arguments[17],
"relViews/getAll/getAll": arguments[18],
"relViews/jobs/jobsView": arguments[19],
"standardViews/IndexView": arguments[20],
"standardViews/dashboardView": arguments[21],
"standardViews/footerView": arguments[22],
"standardViews/headerView": arguments[23],
"standardViews/homeView": arguments[24],
"standardViews/loginView": arguments[25],
"standardViews/overviewView": arguments[26],
"standardViews/pictureView": arguments[27],
"standardViews/portalView": arguments[28],
"standardViews/registeredUsersView": arguments[29],
"standardViews/userProfileView": arguments[30]
}
});
Затем вы можете потребовать модули в своем интерфейсе следующим образом:
var footerView = require("app/js/jsx/standardViews/footerView");
однако, как вы видите, это слишком многословно, так что волшебный способ выглядит так:
назовите зависимость выше как allViews!
теперь вы можете сделать:
var allViews = require('allViews');
var footerView = allViews['standardViews/footerView'];
Есть два преимущества, которые требуют целые каталоги:
(1), с оптимизатором r.js, вы можете указать на одну зависимость (модуль A) и затем легко отследить все зависимости A, которые представляют целую директорию
(2) в разработке, вы можете потребовать целые каталоги спереди, а затем использовать синхронный синтаксис, чтобы требовать зависимости, потому что вы знаете, что они уже загружены
наслаждайтесь "RequireJS-Metagen"
https://www.npmjs.com/package/requirejs-metagen
https://github.com/ORESoftware/requirejs-metagen