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

IT技术 javascript build webpack
2021-02-12 00:51:58

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

我想使用 webpack 并将其分成 4 部分。我不想手动进入并需要我的所有文件。

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

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

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

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

6个回答

这就是我为实现这一目标所做的:

function requireAll(r) { r.keys().forEach(r); }
requireAll(require.context('./modules/', true, /\.js$/));
你能给你提供工作示例 webpack.config.js
2021-03-15 00:51:58
@Joel npmjs.com/package/require-context是在 2017 年创建的,我的回答是从 2015 年开始的,所以很难说它是直接从那里获取的。另请注意,这require-context是一个围绕 的包装器webpack,其示例取自webpack.js.org/guides/dependency-management/#context-module-api 上webpack的文档- 于 2016 年添加(在github.com/webpack/ webpack.js.org/commit/... ),也是在我写下我的答案之后...也许 webpack 的作者受到了我的答案的影响。请注意,他们将其扩展为具有缓存。
2021-03-16 00:51:58
请记住,如果您尝试通过编写一个调用require.context(...)的函数来保持 DRY (例如,如果您试图在多个文件夹中要求所有内容),webpack 将发出警告。参数require.context必须是编译时常量。
2021-03-20 00:51:58
有什么方法可以指定要使用的加载程序吗?我的用例是我想image-size-loader对所有图像使用 ,以便创建具有正确纵横比的占位符。
2021-04-01 00:51:58
@bobbaluba,您可以在配置文件中指定加载程序:loaders: [ { test: /\.json$/, loader: 'json' } ]. { test: /\.json$/, loader: 'json' }为 .json 文件添加 json 加载器,只要你已经安装了加载器。
2021-04-12 00:51:58

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

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

这篇文章的礼貌:https : //github.com/webpack/webpack/issues/118

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

什么是expr在这个例子吗?
2021-03-15 00:51:58
expr即使在查看了 webpack 文档之后,我仍然不清楚基于参数在这里做什么。“这样做不仅仅是为了要求所有 html 文件”是什么意思?谢谢
2021-03-20 00:51:58
我得到了Uncaught ReferenceError: expr is not defined任何提示?
2021-03-27 00:51:58
仍然没有回答expr这里是什么意思
2021-04-06 00:51:58
expr是上下文文件夹中单个文件的路径。所以如果你需要这样做不仅仅是为了需要所有的 html 文件,这很有用。webpack.github.io/docs/context.html#context-module-api
2021-04-09 00:51:58

一个文件夹中所有文件的映射怎么样?

// { 
//   './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 只是返回我的每个文件导出的值 =)。
2021-04-10 00:51:58

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

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导出都聚集在一个{module_name: exports_obj}对象下。
    • module_name是从其文件名构建的。
    • ...没有扩展名并用下划线替换斜线(在子目录扫描的情况下)。
  • 添加了注释以简化自定义。
    • 即您可能不希望在子目录中包含文件,例如,如果它们是根级module手动需要的

编辑:如果像我一样,你确定你的module除了(至少在根级别)一个常规的 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'
    }
  }
}