45

*** Edit - Ignore if you want answer only ***

Seeing as this question is still receiving views and upvotes I feel responsible to share some knowledge after going through the webpack rabbithole and coming out the other end.

If you:

  • are building a greenfield/early-stage modern javascript project
  • are considering migrating from create-react-app
  • don't have much experience with bundling
  • do not need advanced features like module federation or server side rendering (which doesn't need webpack anymore)

Consider using the next generaton bundlers such as vite/parcel (easy setup), esbuild/rollup (more setup required)

Webpack was/is a fantastic contribution to the frontend world and I'm glad I learned all its intricacies, however, the new bundlers are much faster during development and easier to mantain. It's great when it works but for those inexperienced with it; despite fantastic docs the learning curve can make it a horrible pain to debug.

To clarify, I'm not a maintainer on any of these projects - just a dev who enjoys good tooling. In today's landscape, webpack is comparable to using a sledgehammer to crack a nut.

*** End of Edit ***

Webpack newbie here, I was told by webpack cli that I needed to provide an alias for crypto as webpack no longer includes default node libraries. Now I'm getting this error, other answers haven't helped so much. crypto-browserify is trying to access process.browser. Can anyone shed more light? I was told by cli to install stream-browserify too so i did.

React v17, Babel 7.12.9, webpack 5.6.0

webpack.common.js

const paths = require('./paths');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const dotenv = require('dotenv-webpack');

module.exports = {
  entry: [paths.src + '/index.js'],
  output: {
    path: paths.build,
    filename: '[name].bundle.js',
    publicPath: '/',
  },
  plugins: [
    new dotenv(),
    new CleanWebpackPlugin(),
    new CopyWebpackPlugin({
      patterns: [
        {
          from: paths.public,
          to: 'assets',
          globOptions: {
            ignore: ['*.DS_Store'],
          },
        },
      ],
    }),
    new HtmlWebpackPlugin({
      title: 'Webpack Boilerplate',
      // favicon: paths.src + '/images/favicon.png',
      template: paths.src + '/template.html',
      filename: 'index.html',
    }),
  ],
  resolve: {
    fallback: {
      crypto: require.resolve('crypto-browserify'),
      stream: require.resolve('stream-browserify'),
    },
  },
  module: {
    rules: [
      // javascript
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: ['babel-loader'],
      },
      // images
      {
        test: /\.(?:ico|gif|png|jpg|jpeg)$/i,
        type: 'asset/resource',
      },
      // Fonts and SVGs
      {
        test: /\.(woff(2)?|eot|ttf|otf|svg|)$/,
        type: 'asset/inline',
      },
      // CSS, PostCSS, and Sass
      {
        test: /\.(scss|css)$/,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              esModule: true,
              sourceMap: true,
              importLoaders: 1,
              modules: {
                auto: true,
                namedExport: true,
              },
            },
          },
          { loader: 'postcss-loader', options: { sourceMap: true } },
          { loader: 'sass-loader', options: { sourceMap: true } },
        ],
      },
    ],
  },
};

webpack.dev.js

const webpack = require('webpack');
const { merge } = require('webpack-merge');
const common = require('./webpack.common');

module.exports = merge(common, {
  mode: 'development',

  // Control how source maps are generated
  devtool: 'inline-source-map',

  // Spin up a server for quick development
  devServer: {
    historyApiFallback: true,
    contentBase: paths.build,
    open: true,
    compress: true,
    hot: true,
    port: 8080,
  },

  plugins: [
    // Only update what has changed on hot reload
    new webpack.HotModuleReplacementPlugin(),
  ],
});
pacifica94
  • 725
  • 2
  • 6
  • 13

5 Answers5

114

In webpack 5 automatic node.js polyfills are removed. In the migration docs it is mention that

  • Try to use frontend-compatible modules whenever possible.
  • It's possible to manually add a polyfill for a node.js core module. An error message will give a hint on how to achieve that.
  • Package authors: Use the browser field in package.json to make a package frontend-compatible. Provide alternative implementations/dependencies for the browser.

See this issue.

Now you can refer this PR and check the libs that were removed and install them. Next add alias for the lib in your webpack config.

For ex.

resolve: {
    alias: {
       process: "process/browser"
    } 
 }

Update: This can also be done using ProvidePlugin

package.json

"devDependencies": {
   ...
   "process": "0.11.10",
}

webpack.config.js

module.exports = {
  ...
  plugins: [
      new webpack.ProvidePlugin({
             process: 'process/browser',
      }),
  ],
}
Cully
  • 6,427
  • 4
  • 36
  • 58
abhishek khandait
  • 1,990
  • 2
  • 15
  • 18
8

npm i process was all I needed.

Gabriel Arghire
  • 1,992
  • 1
  • 21
  • 34
  • 1
    That may have worked for you, but do you have reason to believe that just installing that package is enough to solve the OP's problem? – camille Mar 23 '22 at 00:03
  • 2
    OP said that `crypto-browserify` is trying to access `process.browser`, so he may not have installed the `process` package. Other than that, nothing. We also need to take into account that people with similar problem will get pointed to this question so this answer may also help them. – Gabriel Arghire Mar 30 '22 at 09:03
1

Hope the correction I proposed will be accepted and released soon

Ran Cohen
  • 171
  • 1
  • 5
0

I have this problem for HtmlWebpackPlugin, I added 'templateParameters' parameter to HtmlWebpackPlugin and it was fixed for me:

new HtmlWebpackPlugin({
      baseUrl: '/',
      template: 'app/index.html',
      templateParameters(compilation, assets, options) {
        return {
          compilation,
          webpack: compilation.getStats().toJson(),
          webpackConfig: compilation.options,
          htmlWebpackPlugin: {
            files: assets,
            options,
          },
          process,
        }
      },
      chunksSortMode: 'auto',
      minify: {
        collapseWhitespace: false,
      },
      cache: true,
    }),
Den Rash
  • 51
  • 7
0
1.  npm i dotenv-webpack    

2.  //Define dotenv in your webpack config
    const Dotenv = require('dotenv-webpack');

    plugins: [
           new Dotenv({
                  path: './.env', // Path to .env file (this is the default)
                  safe: true, // load .env.example (defaults to "false" which does not use dotenv-safe)
                })
    ],
Shahnad S
  • 983
  • 10
  • 17
  • While this code snippet may be the solution, including an explanation really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion. – Shawn Hemelstrand Jan 26 '23 at 09:30