Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Webpack ES6- Load Json with dynamic import (Preserve json file)

I'm trying to split my json files (2 files) into separated chunks. I was able to do it, but there is a "con".

Those json's are converted into .js by webpack, that's why I added a file-loader to .json files, however the await import now returns a string instead of the json.

Webpack rules

module: {
    rules: [
        { test: /\.scss$/, use: [MiniCssExtractPlugin.loader, "css-loader", "postcss-loader", "sass-loader",] },
        { test: /\.woff(\?v=\d+\.\d+\.\d+)?$/, loader: "url-loader?limit=10000&mimetype=application/font-woff&name=fonts/[name].[ext]" },
        { test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/, loader: "url-loader?limit=10000&mimetype=application/font-woff2&name=fonts/[name].[ext]" },
        { test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: "url-loader?limit=10000&mimetype=application/octet-stream&name=fonts/[name].[ext]" },
        { test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: "url-loader?limit=10000&mimetype=application/vnd.ms-fontobject&name=fonts/[name].[ext]" },
        { test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: "url-loader?limit=10000&mimetype=image/svg+xml&name=fonts/[name].[ext]" },
        {
            test: /\.(js|jsx)$/,
            // Skip any files outside of project's `src` directory
            include: [
                path.resolve(__dirname, "../src"),
            ],
            loaders: ["babel-loader"],
        },
        {
            test: /\.json$/,
            type: "javascript/auto",
            loader: "file-loader",
            options: { name: "i18/[name].[ext]" },
            include: [
                path.resolve(__dirname, "../src"),
            ],
        },
        { test: /\.(jpg|png)$/, loader: "url-loader" }
    ]
}

Notice the test: /\.json$/ rule.

Here I'm saying that I want it to be loaded by file-loader instead of the default webpack bundling js.

Note: Without this rule, the app works fine, but I need those .json's

This is the final result:

S1

Both json's are ok. The problem is with i18n.0<...> and i18n.1 which represent en-US and pt-PT.

Now... I'm calling those files using dynamic imports (without transpiling):

/* This loading must be async, it will load the file from the server on-demand */

export const getLanguageFile = async (lang = "en-US") 
   => await import(/* webpackChunkName: "i18n." */ `../i18n/${lang}.json`);

This is then called here:

async componentDidMount() {
    /* Get user info (properties) */
    var properties = await fetch.get("/account/GetUserProperties");

    /* Get language file based in the language code provided in the properties */
    var file = await getLanguageFile(properties.data.LanguageCode);
    this.props.setUserProperties(properties.data, file);
}

This last variable file is assigned with:

S2

This variable should have the full json present in the file.

I know why this is happening, it's because this will call i18n.0<...> instead of the .json, and that file has the following:

(window.webpackJsonp = window.webpackJsonp || [])
    .push(
        [[2], {
            "./src/translations/i18n/en-US.json": function (n, o, s) {
                n.exports = s.p + "i18/en-US.json"
            }
        }]
    );

How may I call those json's using dynamic imports but preserve the full json file?

I need the json because it may be edited in the server-side.

like image 497
Leandro Soares Avatar asked Jun 04 '18 17:06

Leandro Soares


1 Answers

Ok, how did I solve this?

Instead of using import() I just made a xhr request to the file.

But there was a problem, I still needed the files to be in the dist folder.

To do that, I used copy-webpack-plugin, with this you can dump files and folders to anywhere during the bundling process.

I removed my json rule, and added the plugin like this:

new CopyWebpackPlugin([{ from: "src/translations/i18n", to: "i18n" }]),

Ok, it's dumping the i18n folder into the dist:

enter image description here

After this, I changed my function getLanguageFile to:

export const getLanguageFile = async (lang = "en-US") 
   => (await axios.get(`/i18n/${lang}.json`)).data;

This will return the file as json and it all works perfectly.

Note

Development build: webpack-dev-server (Server) + ASP.Net Core (API)

Production build: ASP.Net Core (Server and API)

like image 100
Leandro Soares Avatar answered Nov 08 '22 12:11

Leandro Soares