RobbieC
RobbieC

Reputation: 472

webpack 4 create separate vendor chunk

I'm trying to create a separate vendor chunk (vendor.js) for my project. Right now when I run build everything bundles into my app.js file and the file size is large. My project is a html website with a folder structure in webpack like so:

src/
├── js/
│   └──app.js
├── css/
|   └──app.css
└── images/
└── index.html

My webpack config looks like this:

module.exports = (env, argv) => ({
  mode: argv.mode,
  devtool: argv.mode === 'development' ? 'source-map' : false,
  entry: [
    './src/js/app.js',
    './src/css/app.css'
  ],
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'assets/app.js'
  },
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin(),
      new OptimizeCSSAssetsPlugin(),
      new CopyPlugin({
        patterns: [{
          from: 'src/*.html',
          to: '[name].[ext]'
        }, {
          from: 'src/images/*',
          to: 'images/[name].[ext]'
        }]
      })
    ]
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader'
        }
      }, {
        test: /\.(png|jpg|gif|svg)$/,
        use: [
          {
            loader: 'file-loader',
            options: {
              outputPath: 'images/',
              name: '[name].[ext]'
            }
          }
        ]
      }, {
        test: /.(ttf|otf|eot|woff(2)?)(\?[a-z0-9]+)?$/,
        exclude: /images/,
        use: [
          {
            loader: 'file-loader',
            options: {
              outputPath: 'fonts/',
              name: '[name].[ext]'
            }
          }
        ]
      }, {
        test: /\.(css)$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              publicPath: '../'
            }
          }, {
            loader: 'css-loader'
          }, {
            loader: 'sass-loader',
            options: {
              sourceMap: true
            }
          }, {
            loader: 'postcss-loader',
            options: {
              postcssOptions: {
                plugins: [
                  ['autoprefixer']
                ]
              }
            }
          }, {
            loader: 'sass-loader',
            options: {
              implementation: require('sass')
            }
          }
        ]
      }
    ]
  },
  plugins: [
    new CleanWebpackPlugin(),
    new MiniCssExtractPlugin({
      filename: 'assets/app.css'
    }),
    new ImageminWebpWebpackPlugin({
      config: [{
        test: /\.(jpe?g|png)/,
        options: {
          quality: 76
        }
      }],
      overrideExtension: true,
      detailedLogs: false,
      silent: false,
      strict: true
    })
  ],
  devServer: {
    contentBase: [
      path.join(__dirname, '/src')
    ],
    watchContentBase: true,
    compress: true,
    port: 9000,
    open: true
  }
});

And here is a list of my dependices:

"dependencies": {
    "@barba/core": "^2.8.0",
    "@barba/prefetch": "^2.1.10",
    "fitty": "^2.3.2",
    "gsap": "file:gsap-bonus.tgz",
    "highlight.js": "^10.2.0",
    "imagemin": "^7.0.1",
    "imagemin-webp": "^6.0.0",
    "imagesloaded": "^4.1.4",
    "reset-css": "^5.0.1",
    "smooth-scrollbar": "^8.5.3"
  }

This is my first project in webpack and learned everything from a couple different online videos but none of them covered what im trying to do. I went on webpack documentation and tried to use the Explicit vendor chunk but I was not successful.

My end goal would be to have all my dependencies in a vendor.js file and then my app.js, so my script tag in my index.html would look like this:

<script src="assets/vendor.js"></script> 
<script src="assets/app.js" defer></script>

Upvotes: 1

Views: 1376

Answers (1)

tmhao2005
tmhao2005

Reputation: 17474

I think all you need is to configure split-chunk-plugin. Here is the very simple configuration based on what you need:

// webpack.config.js
module.exports = {
  // ...
  optimization: {
    splitChunks: {
      cacheGroups: {
        commons: {
          chunks: 'initial',
          test: /[\\/]node_modules[\\/]/,
          name: 'vendor',
        },
      },
    },
  },
}

One more thing, if you see error of conflict name, you might need to change the output.filename based on the current file name.

{
  output: {
    filename: "assets/[name].js",
  }
}

Upvotes: 1

Related Questions