如何在不使用require语句的情况下使用webpack加载目录中的所有文件


95

我的应用程序中有大量的javascript文件分成4个子目录。一声不gr,我抓起了所有的并将它们编译成一个文件。这些文件没有module.exports函数。

我想使用webpack并将其分为4部分。我不想手动输入所有文件。

我想创建一个插件,该插件在编译时会遍历目录树,然后获取所有.js文件名和路径,然后要求子目录中的所有文件并将其添加到输出中。

我希望将每个目录中的所有文件编译成一个模块,然后可以从我的入口点文件中将其要求,或者包含在http://webpack.github.io/docs/plugins.html提及的资产中。

添加新文件时,我只想将其放置在正确的目录中,然后知道将包含该文件。

有没有办法使用webpack或有人编写的插件来做到这一点?

Answers:


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' }只要安装了loader,就会为.json文件添加json loader。
杰克

1
请记住,如果您试图通过编写一个调用require.context(...)您的函数来使此处变干(例如,如果您要在多个文件夹中要求所有内容),则webpack将发出警告。参数require.context必须是编译时常量。
艾萨克·莱曼

3
@Joel npmjs.com/package/require-context创建于2017年,我的回答是从2015年开始的,所以很难说它是直接从那里获取的。另请注意,这require-context是一个包装器webpack,其示例摘自webpack.js.org/guides/dependency-management/#context-module-apiwebpack的文档-该文档于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/issues/118

现在正在添加我的所有文件。我有一个用于html和css的加载器,它似乎工作得很好。


27
什么是expr在这个例子吗?
twiz 2015年

2
expr是上下文文件夹中单个文件的路径。因此,如果您不仅需要所有HTML文件,就需要这样做,这很有用。webpack.github.io/docs/context.html#context-module-api
mkoryak

18
expr即使在查看了webpack文档后,我仍然不清楚基于此的论点在做什么。“这不只是要求所有HTML文件”是什么意思?谢谢
mikkelrd

3
我收到了Uncaught ReferenceError:未定义expr。有什么暗示吗?
CSchulz '16

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只是返回我的每个文件导出的值=)。
cacoder

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}对象下。
    • module_name是从其文件名构建的。
    • ...没有扩展名,并用下划线代替斜杠(在扫描子目录时)。
  • 添加了注释以简化自定义。
    • 即,例如,如果根目录模块需要手动在子目录中添加文件,则可能不希望包含这些文件。

编辑:如果像我一样,如果您确定您的模块不会(而不是至少在根级别)返回常规javascript对象以外的任何内容,则还可以“装载”它们以复制其原始目录结构(请参阅代码(深版本) )部分)。

代码(原始版本):

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文件。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.