简体   繁体   中英

Move JSON files from webpack main bundle to own files

I'm building a small web application, where I am loading data from multiple JSON files.

import config from './config.json';
import data from './data.json';

console.log(config, data)

For my webpack build I want to exclude the JSON files from the bundle, since they are quite big (and could be loaded asynchronously). Currently I'm trying to use file-loader to achieve this.

const path = require('path');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  devtool: '#cheap-source-map',
  resolve: {
    modules: ['node_modules']
  },
  entry: {
    main: path.resolve('./index.js')
  },
  output: {
    filename: '[name].bundle.js',
    path: path.resolve('./dist')
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: 'babel-loader'
      },
      {
        type: 'javascript/auto',
        test: /\.json$/,
        use: [
          {
            loader: 'file-loader',
            options: {
              name: '[name].[ext]'
            }
          }
        ]
      }
    ]
  },
  plugins: [
    new CleanWebpackPlugin(),
    new HtmlWebpackPlugin({
      template: './index.html',
      filename: 'index.html',
      inject: 'body'
    })
  ]
};

With this configuration I get separate files, but they won't get imported. In this particular case the console.log() only returns the filename as strings data.json and config.json . It seems like the actual JSON files are not loaded.

What am I doing wrong? Is file-loader the way to go here?

Using file-loader will not do it. The solution is to use the SplitChunksPlugin , which is included in webpack since version 4. For older versions use the CommonsChunkPlugin .

Here is a working webpack.config.json file:

const path = require('path');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  devtool: '#cheap-source-map',
  resolve: {
    modules: ['node_modules']
  },
  entry: {
    main: path.resolve('./index.js')
  },
  output: {
    filename: '[name].bundle.js',
    path: path.resolve('./dist')
  },
  optimization: {
    splitChunks: {
      chunks: 'all',
      minSize: 0,
      cacheGroups: {
        data: {
          test: /\.json$/,
          filename: '[name].js',
          name(module) {
            const filename = module.rawRequest.replace(/^.*[\\/]/, '');
            return filename.substring(0, filename.lastIndexOf('.'));
          },
        }
      }
    }
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: 'babel-loader'
      }
    ]
  },
  plugins: [
    new CleanWebpackPlugin(),
    new HtmlWebpackPlugin({
      template: './index.html',
      filename: 'index.html',
      inject: 'body'
    })
  ]
};

The files get loaded in the app (see requests in DevTools) and console.log(config, data) outputs an array/object.

However, this solution will output the JSON files as JavaScript. This works fine for me, but might be a problem if you rely on the files being JSON. Example for a simple config.json:

(window.webpackJsonp=window.webpackJsonp||[]).push([[1],[function(n){n.exports={name:"test"}}]]);

If you are bothered by the source maps, you can specify an exclude rule with the SourceMapDevToolPlugin .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM