How to build with esbuild code generated by Vue CLI

If you are interested in trying out esbuild with your Vue CLI generated app, in this article I will walk you through setting it up for a freshly generated application. This should be a good starting point for migrating your Vue application to esbuild.

Code generation

I generate new application with:

$ npx -p @vue/cli vue create esbuild-vue-cli -d
  • -d - skips prompts with generating options & use default options - vue version 2
  • npx -p ... - generates code without global installation

The generate code can be build with:

$ npm run build
> esbuild-vue-cli@0.1.0 build
> vue-cli-service build


 DONE  Compiled successfully in 1622ms8:20:58 AM

  File                                 Size               Gzipped

  dist/js/chunk-vendors.5028b17c.js    90.35 KiB          32.40 KiB
  dist/js/app.5b09fec2.js              4.58 KiB           1.63 KiB
  dist/css/app.fb0c6e1c.css            0.33 KiB           0.23 KiB

  Images and other types of assets omitted.

 DONE  Build complete. The dist directory is ready to be deployed.
 INFO  Check out deployment instructions at https://cli.vuejs.org/guide/deployment.html

Key information here - the built code has about 95 KiB, and it took about 1.6s to get it.

Esbuild installation & naive build

First we have to install esbuild:

$ npm install --save-dev esbuild

added 1 package, and audited 1326 packages in 3s

82 packages are looking for funding
  run `npm fund` for details

....

If we were trying to apply the approach used in the create-react-app example, we would en up with a build command in package.json like this one:

{
  ...
  "scripts": {
    ...
    "esbuild": "esbuild src/main.js --bundle --outfile=dist/main.js"
  },
  ...
}

Running this script fails:

$ npm run esbuild

> esbuild-vue-cli@0.1.0 esbuild
> esbuild src/main.js --bundle --outfile=dist/main.js

 > src/main.js:2:16: error: No loader is configured for ".vue" files: src/App.vue
    2 │ import App from './App.vue'
      ╵                 ~~~~~~~~~~~

1 error

There are 2 things happening here:

  • we need a loader for VUE files. Luckily there is a plugin that we can use
  • for using this, or any other esbuild plugin we need to move from building with CLI command to build script - something I already covered here

Installing the plugin & setting the build script

We can install the plugin with:

$ npm install --save-dev esbuild-vue

added 91 packages, and audited 1417 packages in 6s

82 packages are looking for funding
  run `npm fund` for details
...

For the build script, I follow the example form esbuild-vue's Getting started:

const vuePlugin = require("esbuild-vue");

require("esbuild").build({
  entryPoints: ["src/main.js"],
  bundle: true,
  outfile: "dist/main.js",
  logLevel: "info",
  plugins: [vuePlugin()],
  define: {
    "process.env.NODE_ENV": JSON.stringify("development"),
  },
});

Plus I:

  • added logLevel: "info", to get logs about successful builds as well
  • set entryPoints & outfile

Now, we replace the package.json esbuild script with:

{
  ...
  "scripts": {
    ...
    "esbuild": "node build.js"
  },
  ...
}

The build passes:

$ npm run esbuild 

> esbuild-vue-cli@0.1.0 esbuild
> node build.js


  dist/main.js  200.2kb

⚡ Done in 634ms

The build is faster - about 0.6s, but the output is bigger - 200 KiB. Before we will start optimizing it, let's first test if it's working as expected.

For testing our build, let's paste this into dist/index.html:

<!DOCTYPE html>
<html lang="">
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <link rel="icon" href="./favicon.ico" />
    <title>esbuild-vue-cli</title>
  </head>
  <body>
    <noscript
      ><strong
        >We're sorry but esbuild-vue-cli doesn't work properly without
        JavaScript enabled. Please enable it to continue.</strong
      ></noscript
    >
    <div id="app"></div>
    <script src="./main.js"></script>
  </body>
</html>

It's the HTML build by the original npm run build, but tweaked to the files names we used in esbuild. The application works:

Screenshot 2021-07-16 at 08-57-33 esbuild-vue-cli.png

but it's missing a logo. That's because contrary to webpack, esbuild is not parsing HTML files to treat src="<some-file>" as file imports - we will need to do it ourself, but this is something to be covered in other article in this series.

Size optimization

For optimizing the build size, we just need to add to build.js:

...
require("esbuild").build({
  ...
  minify: true,
  ...
});

With this in place, our build is as fast as before:

$ npm run esbuild

> esbuild-vue-cli@0.1.0 esbuild
> node build.js


  dist/main.js  89.9kb

⚡ Done in 600ms

but the size is more or less the same as for the original build script.

Video course

You can check out my course about esbuild.

Summary

In this article, we have seen how to build Vue CLI generate code with esbuild. You can find the code repository here , and the generate page here .