【问题标题】:How to load all files in a directory using webpack without require statements如何在没有require语句的情况下使用webpack加载目录中的所有文件
【发布时间】:2015-06-07 21:46:34
【问题描述】:

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

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

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

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

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

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

【问题讨论】:

    标签: javascript build webpack


    【解决方案1】:

    感谢@splintor(谢谢)。

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

    好处:

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

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

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

        【解决方案3】:

        这对我有用:

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

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

        【讨论】:

          【解决方案4】:

          一个文件夹中所有文件的地图怎么样?

          // { 
          //   './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 只是返回我的每个文件导出的值 =)。
          【解决方案5】:

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

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

          感谢这篇文章:https://github.com/webpack/webpack/issues/118

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

          【讨论】:

          • 本例中的expr 是什么?
          • expr 是上下文文件夹中单个文件的路径。因此,如果您不仅需要所有 html 文件,还需要这样做,这很有用。 webpack.github.io/docs/context.html#context-module-api
          • 即使查看了 webpack 文档,我仍然不清楚基于 expr 的参数在这里做了什么。 “这样做不仅是为了要求所有 html 文件”是什么意思?谢谢
          • 我得到了 未捕获的 ReferenceError: expr is not defined。有什么提示吗?
          • 对于expr在这里的含义仍然没有答案
          【解决方案6】:

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

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

          【讨论】:

          • 有没有办法指定使用什么加载器?我的用例是我想对所有图像使用image-size-loader,以便创建具有正确纵横比的占位符。
          • 能否为您提供工作示例 webpack.config.js
          • @bobbaluba,你可以在配置文件中指定加载器:loaders: [ { test: /\.json$/, loader: 'json' } ]{ test: /\.json$/, loader: 'json' } 为 .json 文件添加 json 加载器,只要你已经安装了加载器。
          • 请记住,如果您尝试在这里通过编写一个为您调用 require.context(...) 的函数来保持 DRY(例如,如果您尝试要求多个文件夹中的所有内容),webpack 将抛出警告. require.context 的参数必须是编译时常量。
          • @Joel npmjs.com/package/require-context 是在 2017 年创建的,我的答案是从 2015 年开始的,所以很难说它是直接从那里得到的。另请注意,require-contextwebpack 的包装器,其样本取自webpackwebpack.js.org/guides/dependency-management/#context-module-api 的文档——该文档于2016 年添加(在github.com/webpack/webpack.js.org/commit/… 中),也是在我写完答案之后。 .. 也许 webpack 的作者受到了我的回答的影响。请注意,他们将其扩展为具有缓存。
          猜你喜欢
          • 1970-01-01
          • 2017-10-22
          • 2017-10-10
          • 1970-01-01
          • 2014-03-16
          • 2018-08-21
          • 1970-01-01
          • 1970-01-01
          • 2015-05-07
          相关资源
          最近更新 更多