Як завантажити всі файли в каталозі за допомогою webpack без необхідних операторів


95

У моєму додатку є велика кількість файлів javascript, розділених на 4 підкаталоги. У грунті я захоплюю їх усіх і збираю в один файл. Ці файли не мають функції module.exports.

Я хочу використовувати webpack і розділити його на 4 частини. Я не хочу вручну входити і вимагати всіх моїх файлів.

Я хотів би створити плагін, який під час компіляції ходить по деревах каталогів, а потім захоплює всі назви файлів .js та шляхи, потім вимагає всіх файлів у підкаталогах та додає їх у вихід.

Я хочу, щоб усі файли в кожному каталозі були зібрані в модуль, який я можу потім вимагати з мого файлу точки входу, або включати до активів, про які згадується http://webpack.github.io/docs/plugins.html .

Додаючи новий файл, я просто хочу занести його у правильний каталог і знати, що він буде включений.

Чи є спосіб зробити це за допомогою вебпакету або плагіна, який хтось написав, щоб зробити це?

Відповіді:


119

Ось що я зробив для досягнення цього:

function requireAll(r) { r.keys().forEach(r); }
requireAll(require.context('./modules/', true, /\.js$/));

Чи є спосіб вказати, який завантажувач використовувати? Мій випадок використання полягає в тому, що я хочу використовувати зображення image-size-loaderдля всіх зображень, щоб створити заповнювачі з правильними співвідношеннями сторін.
bobbaluba

13
не могли б ви надати вам робочий зразок webpack.config.js
Rizwan Patel

2
@bobbaluba, ви можете вказати завантажувач в файлі конфігурації: loaders: [ { test: /\.json$/, loader: 'json' } ]. { test: /\.json$/, loader: 'json' }додає завантажувач json для файлів .json, якщо ви встановили завантажувач.
Джейк

1
Майте на увазі, що якщо ви спробуєте тут бути СУХИМ, написавши функцію, яка закликає require.context(...)вас (наприклад, якщо ви намагаєтесь вимагати все в декількох папках), webpack видасть попередження. Аргументи require.contextповинні бути константами часу компіляції.
Ісаак Ліман

3
@Joel npmjs.com/package/require-context був створений у 2017 році, і моя відповідь - з 2015 року, тому важко сказати, що вона взята прямо звідти. Також зауважте, що require-contextце обгортка навколо webpack, і його зразок взято з webpackдокументації Росії на webpack.js.org/guides/dependency-management/#context-module-api - яка була додана в 2016 році (в github.com/webpack/ webpack.js.org/commit/… ), також після того, як я написав свою відповідь ... Можливо, на мою відповідь вплинули письменники webpack. Зауважте, що вони розширили його, щоб мати кеш.
splintor

38

У своєму файлі додатків я вклав вимогу

require.context(
  "./common", // context folder
  true, // include subdirectories
  /.*/ // RegExp
)("./" + expr + "")

люб’язно надано цю публікацію: https://github.com/webpack/webpack/isissue/118

Зараз додано всі мої файли. У мене є завантажувач для html та css, і він, здається, працює чудово.


27
Що exprв цьому прикладі?
twiz

2
exprце шлях до одного файлу в контекстній папці. тому якщо вам потрібно зробити це не лише для того, щоб вимагати всіх html-файлів, це корисно. webpack.github.io/docs/context.html#context-module-api
mkoryak

18
мені все ще незрозуміло, що exprробиться на цьому аргументі навіть після перегляду документів webpack. що означає "це робити не тільки для того, щоб вимагати всіх html-файлів"? дякую
mikkelrd

3
Я отримав Uncaught ReferenceError: expr не визначено . Будь-який натяк на це?
CSchulz

2
Ще немає відповіді про те, що exprтут означає
wizulus

5

Як щодо карти всіх файлів у папці?

// { 
//   './image1.png':  'data:image/png;base64,iVBORw0KGgoAAAANS',
//   './image2.png':  'data:image/png;base64,iVBP7aCASUUASf892',
// }

Зробити це:

const allFiles = (ctx => {
    let keys = ctx.keys();
    let values = keys.map(ctx);
    return keys.reduce((o, k, i) => { o[k] = values[i]; return o; }, {});
})(require.context('./path/to/folder', true, /.*/));

Дякуємо, відмовившись від цього прикладу. Я використав map просто повернути значення, яке кожен мій файл експортував =).
какодер

1

Приклад того, як отримати карту всіх зображень у поточній папці.

const IMAGES_REGEX = /\.(png|gif|ico|jpg|jpeg)$/;

function mapFiles(context) {
  const keys = context.keys();
  const values = keys.map(context);
  return keys.reduce((accumulator, key, index) => ({
    ...accumulator,
    [key]: values[index],
  }), {});
}

const allImages = mapFiles(require.context('./', true, IMAGES_REGEX));

1

Усі заслуги @splintor (спасибі).

Але ось це моя власна похідна версія.

Переваги:

  • Експорт модулів збирається під {module_name: exports_obj}об'єктом.
    • ім'я_модуля будується з його імені файлу.
    • ... без розширення та заміни косої риски підкресленням (у разі сканування підкаталогів).
  • Додані коментарі для полегшення налаштування.
    • Тобто ви, можливо, захочете не включати файли до підкаталогів, якщо, скажімо, вони є вручну необхідними для модулів кореневого рівня .

EDIT: Якщо, як і я, ви впевнені, що ваші модулі не повернуть нічого іншого (принаймні, на рівні кореня) звичайний об’єкт JavaScript, ви також можете "змонтувати" їх, тиражуючи їх оригінальну структуру каталогів (див. Код (Deep Version) ) розділ в кінці).

Код (оригінальна версія):

function requireAll(r) {
    return Object.fromEntries(
        r.keys().map(function(mpath, ...args) {
            const result =  r(mpath, ...args);
            const name = mpath
                .replace(/(?:^[.\/]*\/|\.[^.]+$)/g, '') // Trim
                .replace(/\//g, '_') // Relace '/'s by '_'s
            ;
            return [name, result];
        })
    );
};
const allModules = requireAll(require.context(
    // Any kind of variables cannot be used here
    '@models'  // (Webpack based) path
    , true     // Use subdirectories
    , /\.js$/  // File name pattern
));

Приклад:

Вибірка зразка для можливих console.log(allModules);:

{
  main: { title: 'Webpack Express Playground' },
  views_home: {
    greeting: 'Welcome to Something!!',
    title: 'Webpack Express Playground'
  }
}

Дерево каталогів:

models
├── main.js
└── views
    └── home.js

Код (глибока версія):

function jsonSet(target, path, value) {
    let current = target;
    path = [...path]; // Detach
    const item = path.pop();
    path.forEach(function(key) {
        (current[key] || (current[key] = {}));
        current = current[key];
    });
    current[item] = value;
    return target;
};
function requireAll(r) {
    const gather = {};
    r.keys().forEach(function(mpath, ...args) {
        const result =  r(mpath, ...args);
        const path = mpath
            .replace(/(?:^[.\/]*\/|\.[^.]+$)/g, '') // Trim
            .split('/')
        ;
        jsonSet(gather, path, result);
    });
    return gather;
};
const models = requireAll(require.context(
    // Any kind of variables cannot be used here
    '@models'  // (Webpack based) path
    , true     // Use subdirectories
    , /\.js$/  // File name pattern
));

Приклад:

Результат попереднього прикладу за допомогою цієї версії:

{
  main: { title: 'Webpack Express Playground' },
  views: {
    home: {
      greeting: 'Welcome to Something!!',
      title: 'Webpack Express Playground'
    }
  }
}

0

це працює для мене:

function requireAll(r) { r.keys().forEach(r); } 

requireAll(require.context('./js/', true, /\.js$/));

ПРИМІТКА: для цього можуть знадобитися файли .js у підкаталогах ./js/ рекурсивно.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.