Saju Thankathurai
Saju Thankathurai

Reputation: 151

Vue 3 vendor bundle is bloated with @babel/parser/lib when vue.esm-bundler.js is used in webpack

I created a Vue 3 project and using webpack for bundling the package. Since I have in-DOM templates, I cannot go with the default @runtime-dom. So I have aliased Vue to point to vue.esm-bundler.js.

The issue I am facing is that, when I take a prod build, my vendor bundle is bloated with @babel/parser/lib.

Sample project to reproduce this issue is available here

Steps to follow:

  1. npm install
  2. npm run bundle

Open dist folder and see the Webpack bundle analyser report.

enter image description here

For ease of config, pasting the configs below.

webpack.config.js

const path = require("path");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer")
  .BundleAnalyzerPlugin;
const { VueLoaderPlugin } = require("vue-loader");
const TerserPlugin = require("terser-webpack-plugin");

module.exports = (env, options) => {
  const devMode = options.mode != "production";
  return {
    context: path.resolve(__dirname, "src"),
    entry: {
      "vue-bundle": "./entry/main.js",
    },
    output: {
      path: path.resolve(__dirname, "dist"),
      filename: "[name].js",
      chunkFilename: "[name].js",
    },
    module: {
      rules: [
        {
          test: /\.js$/,
          exclude: [/node_modules/],
          use: {
            loader: "babel-loader",
            options: {
              presets: [
                [
                  "@babel/preset-env",
                  {
                    targets: [">25%"],
                    debug: true,
                    corejs: "3.6.5",
                    useBuiltIns: false,
                  },
                ],
              ],
            },
          },
        },
        {
          test: /\.vue$/,
          use: "vue-loader",
        },
      ],
    },
    plugins: [
      new CleanWebpackPlugin(),
      new VueLoaderPlugin(),
      new BundleAnalyzerPlugin({        
        openAnalyzer: false,
        analyzerMode: "static",
        reportFilename: "webpack_bundle_analyser_report.html",
        defaultSizes: "gzip",
      }),
    ],
    optimization: {
      mangleWasmImports: true,
      removeAvailableModules: true,
      sideEffects: true,
      minimize: devMode ? false : true,
      minimizer: [
        new TerserPlugin({
          test: /\.js(\?.*)?$/i,
          exclude: /\/node-modules/,
          parallel: 4,
          extractComments: false,
        }),
      ],
      splitChunks: {
        cacheGroups: {
          vendor: {
            test: /[\\/]node_modules[\\/]/,
            name: "vendor-bundle",
            chunks: "all",
          },
        },
      },
    },
    devtool: devMode ? "eval-cheap-source-map" : false,
    resolve: {
      extensions: [".ts", ".js", ".vue", ".json"],
      alias: {
        vue: "vue/dist/vue.esm-bundler.js"
      },
    },
  };
};

package.json

{
  "name": "testPro",
  "version": "1.0.0",
  "private": true,
  "scripts": {
    "bundle": "webpack --mode=production --config webpack.config.js",
    "bundle-dev": "webpack --mode=development --config webpack.config.js"
  },
  "devDependencies": {
    "@babel/core": "^7.12.3",
    "@babel/preset-env": "^7.12.1",
    "@babel/preset-typescript": "^7.12.1",
    "@vue/compiler-sfc": "^3.0.2",
    "babel-loader": "^8.1.0",
    "clean-webpack-plugin": "^3.0.0",
    "core-js": "^3.6.5",
    "regenerator-runtime": "^0.13.7",
    "terser-webpack-plugin": "^5.0.3",
    "vue-loader": "^16.0.0-beta.4",
    "webpack": "^5.3.0",
    "webpack-bundle-analyzer": "^3.9.0",
    "webpack-cli": "^4.1.0"
  },
  "dependencies": {
    "vue": "^3.0.2"
  }
}

Entry file main.js

import { createApp } from 'vue';
import App from '../App.vue';

createApp(App).mount('#app');

Not able to get what I am missing.

Upvotes: 1

Views: 989

Answers (1)

Michal Levý
Michal Levý

Reputation: 37883

I strongly believe it is a bug in Vue 3 so I submitted a bug report - you can track it here

...I reproduced it myself using Vue CLI just to eliminate the chance the problem is in your Webpack config

You have 2 options to workaround this issue:

  1. If you don't need to release right now, just work on your project and wait for a fix (I'm pretty sure it will be fixed - Vue builds for a browser which include compiler does not depend on @babel/parser so it's clear Vue don't need it to work correctly inside browser)
  2. Don't use in-DOM templates and template option (string templates) - put everything in .vue files, <template></template> blocks - Runtime + Compiler vs. Runtime-only. Then you don't need a build with compiler...

EDIT: removed the part about missing process.env.NODE_ENV as --mode param to Webpack CLI does exactly that...

Upvotes: 2

Related Questions