Требовать всю папку - PullRequest
19 голосов
/ 05 мая 2011

Можно ли "требовать" всю папку, используя requireJS.

Например, у меня есть папка поведений с кучей JS-файлов поведения.Мне бы очень хотелось, чтобы можно было просто использовать require (['поведения / *'], function () {...});загружать все в эту папку, а не обновлять этот список.После сжатия и оптимизации все эти файлы будут объединены, но для разработки проще работать с ними по отдельности.

Ответы [ 5 ]

24 голосов
/ 05 мая 2011

JavaScript в браузере не имеет доступа к файловой системе и поэтому не может сканировать каталог на наличие файлов. Если вы создаете свое приложение на языке сценариев, таком как php или ruby, вы можете написать скрипт, который сканирует каталог и добавляет имена файлов к вызову require ().

8 голосов
/ 29 ноября 2013

Хотя 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']);

Затем выполнитьглавная задача.Ваш файл будет создан.Измените ваш main.js, чтобы он загружал namespaces.js

require(['namespaces'], function () { ... });

Таким образом теперь можно разрешить модулям под src использовать зависимости с сопоставлением с шаблоном grunt.

require(['behaviors/**/*'], function (behaviors) { }

Эта идеология предполагает, что у вас есть значимая файловая структура.

5 голосов
/ 19 ноября 2013

Я знаю, что это старое, но я хотел бы поделиться своим решением:

Для этого решения вам нужен JQuery

1) Создать bash-скрипт , который выведет список всех 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
  • Файл будет выглядетьthis:

MyDirectory / FirstJavascriptFile MyDirectory / SecondJavascriptFile MyDirectory / ThirdJavascriptFile

  • Проблема с моим сценарием!Добавляет лишний "" в конце, что все портит!Обязательно удалите лишний пробел в конце 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's 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, заполнив directoryContents.txt.Тогда Моя клиентская сторона просто читает directoryContents.txt для списка файлов, и требует каждого в этом списке.

Надеюсь, это поможет!

1 голос
/ 15 сентября 2015

Я написал библиотеку для решения этой проблемы. В конце концов кто-то пришел и улучшил мою библиотеку, вот она:

https://github.com/smartprocure/directory-metagen

Вы можете использовать мою библиотеку с Gulp или с чем угодно - она ​​генерирует метаданные для вашего проекта, а RequireJS может использовать эти метаданные, чтобы запрашивать нужные файлы из файловой системы.

Использование этой библиотеки приведет к созданию модуля 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]
        }
    });

Затем вам могут потребоваться модули в вашем интерфейсе, например:

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://github.com/smartprocure/directory-metagen

https://www.npmjs.com/package/requirejs-metagen

https://github.com/ORESoftware/requirejs-metagen

1 голос
/ 24 декабря 2013

На самом деле нет способа сделать это концептуально на лету (о чем я знаю).

Есть несколько обходных путей:

Используйте 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, так что рядом с (родным) /js/controllers/init.js находится каталог, называемый "index". Это сделает ваши модули масштабируемыми до заданного интерфейса - вы можете просто поменять модули и сохранить ваш интерфейс прежним.

Надеюсь, это поможет! Удачного кодирования!

...