reactjswebpack-5uglifyjscracoterser-webpack-plugin

I Can See Source Code on Browser Even After I Uglify the Project


My problem is, I can see my source code in browser even after I use Terser Plugin with Webpack. The problem is, I use Terser Plugin for transforming my code into non human readable code chunks. After browsing my files, I am pretty sure chunks and all the gibberish is not human readable. But somehow when I serve the project, I can see my code unminified and/or unuglified with folder structure intact. So the minified and/or uglified version probably improve my load time but if I am able to see source code in the browser, how can I protect it from other clients?

I am guessing, with sourcemaps you can beautify the project. But I can not find a solution if I can manipulate sourcemap or dont use at all. But its just a guess.

Now some technical inputs:

I created the project with CRA and use craco for disrupting original webpack configuration.

const path = require("path");
const TerserPlugin = require("terser-webpack-plugin");

module.exports = (argv) => {
    const webpack = {
        alias: {
            components: path.resolve(__dirname, "src/components"),
            context: path.resolve(__dirname, "src/context"),
            hooks: path.resolve(__dirname, "src/hooks"),
            router: path.resolve(__dirname, "src/router"),
            services: path.resolve(__dirname, "src/services"),
            utilities: path.resolve(__dirname, "src/utilities"),
            uiKit: path.resolve(__dirname, "src/components/uiKit"),
        },

        optimization: {
            runtimeChunk: "multiple",
            splitChunks: {
                chunks: "all",
            },
        },
        entry: {
            index: {
                import: path.resolve(__dirname, "src/index.jsx"),
            },
        },
    };
    if (argv.env && argv.env === "production") {
        webpack.optimization = {
            ...webpack.optimization,
            minimize: true,
            nodeEnv: "production",
            minimizer: [
                new TerserPlugin({
                    terserOptions: {
                        format: {
                            comments: false,
                        },
                        compress: true,
                    },
                    extractComments: false,
                }),
            ],
        };
    }

    return webpack;
};

package.json scripts

        "start": "npx env-cmd -f config/dev.env craco start",
        "build:test": "npx env-cmd -f config/test.env craco build",
        "build:prod": "npx env-cmd -f config/prod.env craco build",

package.json Dev Dependencies

    "devDependencies": {
        "@babel/plugin-proposal-private-property-in-object": "^7.21.11",
        "@craco/craco": "^7.1.0",
        "@storybook/addon-essentials": "^7.0.26",
        "@storybook/addon-interactions": "^7.0.26",
        "@storybook/addon-links": "^7.0.26",
        "@storybook/addon-styling": "^1.3.2",
        "@storybook/blocks": "^7.0.26",
        "@storybook/preset-create-react-app": "^7.0.26",
        "@storybook/react": "^7.0.26",
        "@storybook/react-webpack5": "^7.0.26",
        "@storybook/testing-library": "^0.0.14-next.2",
        "autoprefixer": "^10.4.14",
        "babel-eslint": "^10.1.0",
        "babel-plugin-named-exports-order": "^0.0.2",
        "clean-jsdoc-theme": "^4.2.9",
        "env-cmd": "^10.1.0",
        "eslint": "^8.42.0",
        "eslint-plugin-react": "^7.32.2",
        "eslint-plugin-react-hooks": "^4.6.0",
        "eslint-plugin-storybook": "^0.6.12",
        "jsdoc": "^4.0.2",
        "jsdoc-to-markdown": "^8.0.0",
        "postcss": "^8.4.25",
        "storybook": "^7.0.26",
        "tailwindcss": "^3.3.2",
        "terser-webpack-plugin": "^5.3.10",
        "webpack": "^5.88.1"
    }

package.json dependencies

"dependencies": {
        "@arcgis/core": "^4.27.6",
        "@loadable/component": "^5.15.3",
        "@mapbox/mapbox-gl-draw": "^1.4.3",
        "@rive-app/react-canvas": "^4.3.3",
        "@turf/turf": "^6.5.0",
        "axios": "^1.4.0",
        "cbs-panorama": "^1.0.65",
        "clsx": "^1.2.1",
        "express": "^4.18.2",
        "geojson-to-svg": "^1.1.4",
        "hls.js": "^1.4.10",
        "i18next": "^23.3.0",
        "i18next-browser-languagedetector": "^7.1.0",
        "i18next-http-backend": "^2.2.1",
        "maplibre-gl": "3.6.2",
        "proj4": "^2.9.2",
        "prop-types": "^15.8.1",
        "react": "^18.2.0",
        "react-color": "^2.19.3",
        "react-dom": "^18.2.0",
        "react-i18next": "^13.0.2",
        "react-icomoon": "^2.5.7",
        "react-router-dom": "^6.11.1",
        "swiper": "^10.2.0",
        "three": "^0.162.0",
        "web-vitals": "^2.1.4"
    },

Code in folder

Code Context

enter image description here

Code in the Browser

enter image description here

As you can see code in folder looks uglified but not in the browser. I am guessing it is related to sourcemap but may be something else.


Solution

  • The problem is caused by the syntax difference between webpack and craco. "devtool" and "optimization" keys must be nested within the "configure" key.

    you can do it this way:

    module.exports = {
    webpack: {
        mode: 'production',
        alias: {
            components: path.resolve(__dirname, "src/components"),
            context: path.resolve(__dirname, "src/context"),
            hooks: path.resolve(__dirname, "src/hooks"),
            router: path.resolve(__dirname, "src/router"),
            services: path.resolve(__dirname, "src/services"),
            utilities: path.resolve(__dirname, "src/utilities"),
            uiKit: path.resolve(__dirname, "src/components/uiKit"),
        },
        entry: {
      index: {
        import: path.resolve(__dirname, "src/index.jsx")
      },
    },
        configure: {
            devtool: false, 
            optimization : {
                runtimeChunk: "multiple",
                splitChunks: {
                    chunks: "all",
                },
                minimize: true,
                minimizer: [
                    new TerserPlugin({
                        terserOptions: {
                            format: {
                                comments: false,
                            },
                            compress: true,
                        },
                        extractComments: false,
                    }),
                ],
            }
        }
    } }
    

    happy coding :)