Error: Conflict: Multiple Chunks Emit

Hello,

I am creating a component that contains css, js, and tsx files together. But when I debug it, I got this error:[webpack-cli] Error: Conflict: Multiple chunks emit assets to the same filename RadComponents.js (chunks RadComponents and styles)

I tried to change my webpacl.config.js file but I couldn't solve it. If anyone faced with the same error, it would be great to share it with me!

Thanks.

Here is my webpack.config.file:

/**
 * Webpack build configuration file.  Uses generic configuration that is appropriate for development.  Depending on
 * the needs of your module, you'll likely want to add appropriate 'production' configuration to this file in order
 * do do things such as minify, postcss, etc.
 *
 * To learn more about webpack, visit https://webpack.js.org/
 */

const webpack = require('webpack'),
    path = require('path'),
    fs = require('fs'),
    MiniCssExtractPlugin = require("mini-css-extract-plugin"),
    AfterBuildPlugin = require('@fiverr/afterbuild-webpack-plugin');

const LibName = "RadComponents";

// function that copies the result of the webpack from the dist/ folder into the  generated-resources folder which
// ultimately gets included in a 'web.jar'.  This jar is included in the module's gateway scope, and its contents are
// accessible as classpath resources just as if they were included in the gateway jar itself.
function copyToResources() {
    const generatedResourcesDir = path.resolve(__dirname, '../..', 'build/generated-resources/mounted/');
    const jsToCopy = path.resolve(__dirname, "dist/", `${LibName}.js`);
    const cssToCopy = path.resolve(__dirname, "dist/", `${LibName}.css`);
    const jSResourcePath = path.resolve(generatedResourcesDir, `${LibName}.js`);
    const cssResourcePath = path.resolve(generatedResourcesDir, `${LibName}.css`);


    const toCopy = [{from:jsToCopy, to: jSResourcePath}, {from: cssToCopy, to: cssResourcePath}];

    // if the desired folder doesn't exist, create it
    if (!fs.existsSync(generatedResourcesDir)){
        fs.mkdirSync(generatedResourcesDir, {recursive: true})
    }

    toCopy.forEach( file => {
        console.log(`copying ${file} into ${generatedResourcesDir}...`);

        try {
            fs.access(file.from, fs.constants.R_OK, (err) => {
                if (!err) {
                    fs.createReadStream(file.from)
                        .pipe(fs.createWriteStream(file.to));
                } else {
                    console.log(`Error when attempting to copy ${file.from} into ${file.to}`)
                }
            });
        } catch (err) {
            console.error(err);
            // rethrow to fail build
            throw err;
        }
    });
}


const config = {

    // define our entry point, from which we build our source tree for bundling
    entry: {
        RadComponents:  path.join(__dirname, "./typescript/rad-client-components.ts")
    },

    output: {
        library: [LibName],  // name as it will be accessible by on the webpack when linked as a script
        path: path.join(__dirname, "dist"),
        filename: `${LibName}.js`,
        libraryTarget: "umd",
        umdNamedDefine: true
    },

    // Enable sourcemaps for debugging webpack's output.  Should be changed for production builds.
    devtool: "source-map",

    resolve: {
        extensions: [".jsx", ".js", ".ts", ".tsx", ".d.ts", ".css", ".scss"],
        modules: [
            path.resolve(__dirname, "../../node_modules")  // look at the local as well as shared node modules when resolving dependencies
        ]
    },

    module: {
        rules: [
            {
                test: /\.tsx?$/,
                use: {
                    loader: 'ts-loader',
                    options: {
                        transpileOnly: false
                    }
                },
                exclude: /node_modules/,
            },

            {
                test: /\.html$/,
                use: {
                    loader: 'html-loader',
                    options: {
                        minimize:true
                    }
                },
                exclude: /node_modules/,
            },
            {
                test: /\.(js|jsx)$/,
                exclude: /node_modules/,
                use: {
                    loader: "babel-loader",
                    options: {
                        presets: ["@babel/preset-env", "@babel/preset-react"]
                    }
                }
            },

            {
                test: /\.css$|.scss$/,
                use: [
                    MiniCssExtractPlugin.loader,
                    {
                        loader: 'css-loader',
                        options: {
                            // tells css-loader not to treat `url('/some/path')` as things that need to resolve at build time
                            // in other words, the url value is simply passed-through as written in the css/sass
                            url: false
                        }
                    },
                    {
                        loader: "sass-loader",
                    }
                ]
            }
        ]
    },
    plugins: [
        new AfterBuildPlugin(function(stats) {
            copyToResources();
        }),
        // pulls CSS out into a single file instead of dynamically inlining it
        new MiniCssExtractPlugin({
            filename: "[name].css"
        })
    ],

    // IMPORTANT -- this tells the webpack build tooling "don't include these things as part of the webpack bundle".
    // They are 'provided' 'externally' via perspective/ignition at runtime, and we don't want multiple copies in the
    // browser.  Any libraries used that are also used in perspective should be excluded.
    externals: {
        "react": "React",
        "react-dom": "ReactDOM",
        "mobx": "mobx",
        "mobx-react": "mobxReact",
        "@inductiveautomation/perspective-client": "PerspectiveClient"
    },
    optimization: {
        splitChunks: {
            cacheGroups: {
                styles: {
                    name: 'styles',
                    test: /\.css$/,
                    chunks: 'all',
                    enforce: true,
                },
            },
        },
    },
};


module.exports = () => config;

It has something to do with the output config. but the configs should be fine from the git example...
Maybe you have two "RadComponents", the original and the new one you made?

Deleting the cache might also help

Thanks for your comment. But I didn't create another component. Normally, when I create a new .tsx file and debug it, I am able to use it in my Ignition designer. But when I want to import a .js file into my .tsx file, I need to change webpack.config file according to requirements of how to read a js file (babel-loader). After changes, I think, but I am not sure, webpack.config file try to create two different output file with the same name which is RadComponents.js.

how so?

this one i added in rules section:

 {
                test: /\.(js|jsx)$/,
                exclude: /node_modules/,
                use: {
                    loader: "babel-loader",
                    options: {
                        presets: ["@babel/preset-env", "@babel/preset-react"]
                    }
                }
            },

I could be wrong. If I am wrong let me know the correct one :smiley: .

ahhh yes, thats wrong. It shouldnt be there, you can remove it.
Why did you add it?
if you just import the js inside your tsx file, then you dont need to add it in seperately.

You might have to enable js, in the tsconfig.json, if it doenst compile

compilerOptions{
...
"allowJs": true,
}

I already changed it to true. When I delete babel-loader section, I get this error:

ERROR in ./typescript/components/App.js 13:12
Module parse failed: Unexpected token (13:12)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
|     return (
| 
>             <SomeEditor
|                 onInit={(evt, editor) => editorRef.current = editor}


:woozy_face: Although, I tried to use chunk for changing name of components, It doesn't work.

how are you importing the js file?

you could try to replace this, idk if its the cause,

with this

{
                test:/\.(js|jsx|ts|tsx)$/,
                exclude: /node_modules/,
                use: {
                    loader: "babel-loader",
                    options: {
                        presets: ["@babel/preset-env", "@babel/preset-react"]
                    }
                }
            },

I just did import SomeEditor from './SomeEditor'

Now, when I replace it with you typed, error has been changed:

ERROR in ./typescript/rad-client-components.ts
Module build failed (from ../../node_modules/babel-loader/lib/index.js):
SyntaxError: C:\Users\bkose\OneDrive\Desktop\testing\perspective-component\web\packages\client\typescript\rad-client-components.ts: Missing initializer in const declaration. (11:16)

   9 |
  10 | // as new components are implemented, import them, and add their meta to this array
> 11 | const components: Array<ComponentMeta> = [
     |                 ^
  12 |     new ImageMeta(),
  13 |     new MessengerComponentMeta(),
  14 |     new TagCounterMeta()

Maybe, is there anything else i miss?

hm thats a worse error xd seems you just need the ts-loader like before...

are you exporting the someEditor as default?

ohterwise no idea,

Yes, default. If i have find any solution about this, i will update it. Thanks for your help :+1:t3:

2 Likes