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

How to load all files in a directory using webpack without require statements

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

我想用webpack,把它分成4个部分。我不想手动进入并要求我的所有文件。

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

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

添加新文件时,我只想将它放到正确的目录中并知道它会被包含。

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

在我的应用程序文件中,我最终添加了要求

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

感谢 post:https://github.com/webpack/webpack/issues/118

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

我就是这样做的:

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

文件夹中所有文件的映射如何?

// { 
//   './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, /.*/));

这对我有用:

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

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

注意:这可能需要 ./js/ 的子​​目录中递归的 .js 文件。

如何获取当前文件夹中所有图像的地图的示例。

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));

感谢@splintor(感谢)。

但这里是我自己的衍生版本。

好处:

  • 什么模块导出被收集在一个{module_name: exports_obj}对象下。
    • module_name 是根据其文件名构建的。
    • ...没有扩展名并用下划线替换斜杠(在子目录扫描的情况下)。
  • 添加注释以简化自定义。
    • 即如果 root 级别 模块需要手动需要这些文件,您可能不想在子目录中包含文件。

EDIT: If, like me, you're sure your modules won't return anything else than (at least at root level) a regular javascript object, you can also "mount" them replicating their original directory structure (see Code (Deep Version) section at the end).

代码(原版):

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'
    }
  }
}