Reputation: 2087
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?
Upvotes: 3
Views: 2263
Reputation: 2087
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.
Upvotes: 1