Webpack:我可以提供一个字符串中的"virtual"文件吗?



我的Webpack应用程序中有一些在构建时创建的JSON-有什么方法可以在构建过程中用路径"注入"它吗?我知道我可以把它写在一个文件中,并以这种方式包含它,但我希望我能做一些更干净的事情。

编辑2020/10/27:webpack虚拟模块是一个可以做到这一点的项目,并且与webpack 5 兼容

Edit 2018/04/09:val加载程序是在构建时实现注入代码和值的另一种方法,但它需要从一个单独的文件加载该代码,如果该文件仅存在于内存中,则该文件可能无法访问OP设置中的JSON数据。

我也在想办法做到这一点。我最终深入研究了webpack的内部结构,并编写了一个似乎可以工作的插件。

它很干净,因为你不必将文件写入磁盘,但它的内部有点混乱,因为我必须了解webpack的CachedInputFileSystem是如何工作的。

使用加载器似乎不可能做到这一点。Webpack需要解析磁盘上的文件位置并读取其中的内容,然后才能进入加载阶段。

通过在compiler.resolvers.normal的"解析"阶段放置插件函数,可以访问webpack正在使用的文件系统,然后将虚拟文件名和内容添加到该文件系统的缓存中。

完成后,webpack中的其他一切都正常工作,您的虚拟文件/模块将通过您配置的其他加载程序和插件。

请参阅https://github.com/rmarscher/virtual-module-webpack-plugin我写的代码。已发布到npm:https://www.npmjs.com/package/virtual-module-webpack-plugin

以下是插件解析部分的代码。注意,这个例子是针对webpack 1和2的,但插件已经更新,可以使用更新的版本:

compiler.resolvers.normal.plugin('resolve', function resolverPlugin(request, cb) {
  // populate the file system cache with the virtual module
  const fs = this.fileSystem;
  // webpack 1.x compatibility
  if (typeof request === 'string') {
    request = cb;
    cb = null;
  }
  if (!modulePath) {
    modulePath = this.join(compiler.context, moduleName);
  }
  VirtualModulePlugin.populateFilesystem({ fs, modulePath, contents, ctime });
  if (cb) {
    cb();
  }
});

populateFilesystem静态方法将内容添加到fs._readFileStorage.data,并在fs._statStorage.data高速缓存中为fs.stat()创建模拟结果。为了创建mock fs.Stats对象,我借用了mock-fs包中的一些代码。

到目前为止,我已经用最新的webpack1.x和2.x以及webpack-dev服务器对它进行了测试。我使用了extract-text-webpack-pluginjson-loaderraw-loadercss-loader。一切似乎都如预期的那样。

以下是使用插件的webpack配置:

'use strict';
const path = require('path');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const VirtualModulePlugin = require('virtual-module-webpack-plugin');
module.exports = function webpackConfig() {
  const runtimeJsonContents = JSON.stringify({
    greeting: 'Hello!',
  });
  const runtimeStyleContents = `
    body { background: #000; color: #ccc; }
    .greeting { font: 600 40px/50px fantasy; text-align: center; }
  `;
  const config = {
    context: __dirname,
    devtool: 'source-map',
    entry: {
      index: './src/index',
    },
    output: {
      filename: '[name].js',
      path: 'dist',
      publicPath: '/',
      devtoolModuleFilenameTemplate: '../[resource-path]',
    },
    module: {
      loaders: [
        {
          test: /.json$/,
          loaders: ['json-loader'],
        },
        {
          test: /.css$/,
          loader: ExtractTextPlugin.extract({
            fallbackLoader: 'style-loader',
            loader: 'css-loader?sourceMap',
          }),
        },
      ],
    },
    plugins: [
      new VirtualModulePlugin({
        moduleName: 'src/mysettings.json',
        contents: runtimeJsonContents,
      }),
      new VirtualModulePlugin({
        moduleName: 'src/css/generated.css',
        contents: runtimeStyleContents,
      }),
      new ExtractTextPlugin({
        filename: '[name].css',
        allChunks: true,
      }),
    ],
    resolve: {
      modules: [
        path.join(__dirname, 'src'),
        'node_modules',
      ],
    },
  };
  return config;
};

请参阅https://github.com/rmarscher/virtual-module-webpack-plugin/tree/master/examples获取不同版本的webpack的完整示例。

我还应该注意,此代码需要NodeJS 4.x或更高版本。

最新更新