Vue Babel Config

Posted on  by admin

Configuration #

You block advertising 😢Would you like to buy me a ☕️ instead? For my previous article about three different ways of how to structure a Vue.js application, I wanted to set up a build system which not only allows for regular JavaScript code splitting, but also CSS code splitting.

Thanks to webpack 4 and the mini-css-extract-plugin (which basically is the successor of the extract-text-webpack-plugin), CSS code splitting is finally possible.

Like What You Read?

I quickly realized though, that there is currently no official way of how to setup a webpack 4 powered Vue.js development environment.

# Unit Testing

Both the current Vue.js webpack template and the vue-cli (which is currently in beta), are still using webpack 3. So I decided to set up a webpack 4 powered build process myself. This tutorial focuses exclusively on how to configure webpack, you can see the application code on GitHub and you can check out a live demo on Netlify.

In this article, we’ll focus on the bare minimum build setup we need to build a very basic Vue.js application.

If you’re planning to set up the build process for a large scale application, you should consider using the new vue-cli instead of rolling your own.

Parallelization #

That said, I think it is very useful to know how stuff works, so let’s start to explore how to build our own basic webpack configuration for bundling a Vue.js application.

Injected webpack-chain Rules #

  • First of all, we have to install some (a lot of) dependencies which we’ll need for our basic configuration.

  • Let me explain why we need some of the most important packages in this long list of dependencies.

    @babel/core and @babel/preset-env are needed for transpiling ES6 code into code which is also understood by older browsers. The @babel/plugin-syntax-dynamic-import package is needed for dynamic imports (which are used for code splitting) to work. We’ll use the cross-env package, to define environment variables in a way all operating systems can handle.

    We’re requiring the 8.x beta build of babel-loader because the current stable 7.x version, does not work with Babel 7. The 15.x beta build of the vue-loader package is mainly used because it is a vast improvement over older versions. What you can see above, is the most basic configuration possible to enable webpack 4 to process .vue files and compile Sass into regular CSS.

    You might notice, that I skipped configuring a regular CSS loader, if you want to also process regular CSS, take a look at the official vue-loader documentation for an example of how to configure the css-loader. Before we can build our application, we still have to configure Babel.

    Let’s create a .babelrc file in the root directory of our project.

    The reason why the modules option of the @babel/preset-env configuration is set to false is because we want webpack to handle module bundling for us.

    • Thanks to the latest beta version of vue-loader, it is finally possible to use custom node-sass importers with Vue.js.

    • This makes it possible to use the node-sass-magic-importer to do fancy things with Sass like selector-filtering which means importing only specific CSS selectors, glob imports to enable glob patterns like **/*.scss to import multiple .scss files at once or node-filtering which makes it possible to only import variables and mixins for example.

    After installing the dependency, we can add the custom importer to the webpack configuration. Now we’re ready to build our application with webpack.

Caching #

  • Let’s add a new npm script for starting our build process.

  • We can start the build process by running npm run build, which creates a bundled version of our application ready to be served from the dist/ directory.

    In order to being able to comfortable work on our application, we don’t want to run the build process manually every time we make a small change to the code. Instead we want webpack to watch our code and start the build process automatically after every change.

    Also we want our browser to display those changes immediately without reloading the application.

    We can achieve this with the webpack-serve package and hot reloading. First we have to install the dependencies we’ll need, next we can create a little development server script.

Do you want to learn more about advanced Vue.js techniques?

  • The script above starts a development server powered by the webpack-serve package.

  • After the server was started, your browser should automatically be opened and load the application, thanks to the openBrowser() function we’ll implement in the next step.

    The code for the openBrowser() function you can see above, is stolen from the vue-cli project. Additionally to the code above, you also need a .applescript file which was originally created by Facebook, you can find the file in the GitHub repository accompanying this article.

    What it does is, that (if you’re running macOS and using Google Chrome as your default browser) it tries to reuse an existing tab (which is already running our application) every time the development server is started.

    By adding a new serve:dev script, and also adding a start script as an alias of the first, we’re now able to run our application in development mode with hot reloading enabled by executing npm start.

Installing in an Already Created Project #

  • To enhance the development experience even further, we can enable source maps, which give us the benefit of the browser showing us the correct file names and line numbers in case we’re debugging JavaScript or CSS code.

  • Although we’re now already able to build our application, and thanks to webpack 4 which automatically minifies JavaScript code in production mode, the built code is already kinda production ready.

    But for now, all the CSS code is bundled alongside the JavaScript code. This makes it impossible to cache the CSS code separately from the JavaScript code – if either the CSS or the JavaScript code changes, both have to be downloaded again by the client.

Wrapping it up

  • Additionally, the browser has more work to do if the CSS code has to be processed inside the JavaScript code.

  • For those two reasons, we want to extract the CSS code from the JavaScript bundles and serve regular .css files to the client instead.

    The mini-css-extract-plugin makes it possible to extract CSS code from JavaScript bundles. To make the mini-css-extract-plugin do its work, we have to update our webpack.config.js file. If webpack is started in production mode, we add a new instance of the MiniCssExtractPlugin() to the list of plugins.

What's your use case?

  • Also we’re replacing the vue-style-loader in the sass-loader configuration (the vue-style-loader is on position 0 of the use array) with the MiniCssExtractPlugin.loader.

  • If we build our application again, we can see, that the CSS code is now extracted and split into multiple separate CSS files.

    Similar to the JavaScript code splitting feature, the mini-css-extract-plugin is able to split CSS code so only code necessary for rendering the current chunk is loaded.

    • You might notice that although the JavaScript code is perfectly minified, thats not true for the extracted CSS code. To fix that, we have to configure minification manually. After installing the necessary plugins, we can update our webpack.config.js file. Register for the Newsletter of my upcoming book: Advanced Vue.js Application Architecture.
    • Finally our production build satisfies all our basic needs.

    We have code splitting enabled (for both JavaScript and CSS) and everything is minified nicely.

    Now let’s write a simple SPA server script to serve the production build of our application. The only dependency we need, is the express server package. The code above, starts a very basic express server which either returns a static file (if one is requested) or the index.html inside of our dist/ directory for every other request.

# Babel

  • After adding a new npm script for starting our SPA server, we can run npm run serve:production to serve our application.

  • Follow me to get my latest Vue.js articles.

    Although I’d not recommend to roll your own build setup for large scale applications (use vue-cli instead), I think it is important to know at least the basics of how to configure webpack.

    Also, it can be very useful to set up your own build process for small scale or experimental applications and although doing so is still not as straightforward as I’d wish, webpack 4 is a huge step forward in that regards. Babel can be configured!

    Many other tools have similar configs: ESLint (.eslintrc), Prettier (.prettierrc). All Babel API options are allowed. However, if the option requires JavaScript, you may want to use a JavaScript configuration file.

    You are using a monorepo? You want to compile node_modules? babel.config.json is for you! You have a configuration that only applies to a single part of your project?

    .babelrc.json is for you! Guy Fieri is your hero? We recommend using the babel.config.json format.

    Babel itself is using it. Create a file called babel.config.json with the following content at the root of your project (where the package.json is). Check out the babel.config.json documentation to see more configuration options.

# Global CLI Config

  • Create a file called .babelrc.json with the following content in your project.

  • Check out the .babelrc documentation to see more configuration options.

    Alternatively, you can choose to specify your .babelrc.json config from within package.json using the babel key like so:. You can also write babel.config.json and .babelrc.json files using JavaScript:. You are allowed to access any Node.js APIs, for example a dynamic configuration based on the process environment:.

    You can read more about JavaScript configuration files in the dedicated documentation.

# TypeScript

  • Check out the babel-cli documentation to see more configuration options.

  • Check out the babel-core documentation to see more configuration options.

    You can tell Babel to print effective configs on a given input path. BABEL_SHOW_CONFIG_FOR accepts both absolute and relative file paths. If it is a relative path, it will be resolved from cwd.

    Once Babel processes the input file specified by BABEL_SHOW_CONFIG_FOR, Babel will print effective configs to the console. Here is an example output:. Babel will print effective config sources ordered by ascending priority.

Using the example above, the priority is:.

In other words, babel.config.json is overwritten by .babelrc, and .babelrc is overwritten by programmatic options. For each config source, Babel prints applicable config items (e.g. overrides and env) in the order of ascending priority.

Generally each config sources has at least one config item -- the root content of configs. If you have configured overrides or env, Babel will not print them in the root, but will instead output a separate config item titled as .overrides[index], where index is the position of the item.

This helps determine whether the item is effective on the input and which configs it will override.

# ESLint

  • If your input is ignored by ignore or only, Babel will print that this file is ignored.

  • Babel's configuration merging is relatively straightforward.

    Options will overwrite existing optionswhen they are present and their value is not undefined. There are, however, a few special cases:.

Configuring webpack 4 for Vue.js

  • For assumptions, parserOpts and generatorOpts, objects are merged, rather than replaced.

  • For plugins and presets, they are replaced based on the identity of the plugin/preset object/function itself combined with the name of the entry.

    As an example, consider a config with:. When NODE_ENV is test, the sourceType option will be replaced and the assumptions option will be merged.

    The effective config is:. As an example, consider a config with:. The overrides item will be merged on top of the top-level options. Importantly, the pluginsarray as a whole doesn't just replace the top-level one.

    The merging logic will see that "./plug"is the same plugin in both cases, and { thing: false, field2: true } will replace the originaloptions, resulting in a config as.

Print effective configs

  • Since merging is based on identity + name, it is considered an error to use the same plugin withthe same name twice in the same plugins/presets array.

  • is considered an error, because it's identical to plugins: ['./plug'].

    Additionally, even. is considered an error, because the second one would just always replace the first one. If you actually do want to instantiate two separate instances of a plugin, you must assign each onea name to disambiguate them.

    because each instance has been given a unique name and thus a unique identity. Some global configurations for @vue/cli, such as your preferred package manager and your locally saved presets, are stored in a JSON file named .vuerc in your home directory.

    You can edit this file directly with your editor of choice to change the saved options. You can also use the vue config command to inspect or modify the global CLI config.

# vue.config.js

  • See the Browser Compatibility section in guide.

    vue.config.js is an optional config file that will be automatically loaded by @vue/cli-service if it's present in your project root (next to package.json).

    You can also use the vue field in package.json, but do note in that case you will be limited to JSON-compatible values only. The file should export an object containing options:.

    Deprecated since Vue CLI 3.3, please use publicPath instead.

Browse other questions tagged vue.jsvuejs2babeljsbabel-loader or ask your own question.

  • The base URL your application bundle will be deployed at (known as baseUrl before Vue CLI 3.3).

    This is the equivalent of webpack's output.publicPath, but Vue CLI also needs this value for other purposes, so you should always use publicPath instead of modifying webpack output.publicPath.

    By default, Vue CLI assumes your app will be deployed at the root of a domain, e.g.

Using the CLI (@babel/cli)

# Target Browsers If your app is deployed at a sub-path, you will need to specify that sub-path using this option.

Using the API (@babel/core)

  • For example, if your app is deployed at, set publicPath to '/my-app/'.

  • The value can also be set to an empty string ('') or a relative path (./) so that all assets are linked using relative paths.

    This allows the built bundle to be deployed under any public path, or used in a file system based environment like a Cordova hybrid app.

    Limitations of relative publicPath. Relative publicPath has some limitations and should be avoided when:.

    You are using HTML5 history.pushState routing;. You are using the pages option to build a multi-paged app. This value is also respected during development.

    If you want your dev server to be served at root instead, you can use a conditional value:. Default: 'dist'. The directory where the production build files will be generated in when running vue-cli-service build.

    Note the target directory will be removed before building (this behavior can be disabled by passing --no-clean when building). Always use outputDir instead of modifying webpack output.path.

# E2E Testing

  • A directory (relative to outputDir) to nest generated static assets (js, css, img, fonts) under.

  • assetsDir is ignored when overwriting the filename or chunkFilename from the generated assets.

    Default: 'index.html'. Specify the output path for the generated index.html (relative to outputDir).

Not the answer you're looking for? Browse other questions tagged node.jsvue.jsvuejs2 or ask your own question.

  • Can also be an absolute path.

  • By default, generated static assets contains hashes in their filenames for better caching control.

    However, this requires the index HTML to be auto-generated by Vue CLI.

    If you cannot make use of the index HTML generated by Vue CLI, you can disable filename hashing by setting this option to false.

    Default: undefined. Build the app in multi-page mode. Each "page" should have a corresponding JavaScript entry file. The value should be an object where the key is the name of the entry, and the value is either:.

    An object that specifies its entry, template, filename, title and chunks (all optional except entry).

    Any other properties added beside those will also be passed directly to html-webpack-plugin, allowing user to customize said plugin;.

    Or a string specifying its entry. When building in multi-page mode, the webpack config will contain different plugins (there will be multiple instances of html-webpack-plugin and preload-webpack-plugin).

# parallel

  • Make sure to run vue inspect if you are trying to modify the options for those plugins.

    Type: boolean | 'warning' | 'default' | 'error'. Whether to perform lint-on-save during development using eslint-loader.

    • This value is respected only when @vue/cli-plugin-eslint is installed. When set to true or 'warning', eslint-loader will emit lint errors as warnings.

    • By default, warnings are only logged to the terminal and does not fail the compilation, so this is a good default for development. To make lint errors show up in the browser overlay, you can use lintOnSave: 'default'.

# outputDir

  • This will force eslint-loader to actually emit errors.

    this also means lint errors will now cause the compilation to fail. Setting it to 'errors' will force eslint-loader to emit warnings as errors as well, which means warnings will also show up in the overlay. Alternatively, you can configure the overlay to display both warnings and errors:.

    When lintOnSave is a truthy value, eslint-loader will be applied in both development and production.

    If you want to disable eslint-loader during production build, you can use the following config:. Whether to use the build of Vue core that includes the runtime compiler.

    Setting it to true will allow you to use the template option in Vue components, but will incur around an extra 10kb payload for your app.

    See also: Runtime + Compiler vs. Type: Array. By default babel-loader ignores all files inside node_modules. If you want to explicitly transpile a dependency with Babel, you can list it in this option.

    This option is not respected by the cli-unit-jest plugin, because in jest, we don't have to transpile code from /node_modules unless it uses non-standard features - Node >8.11 supports the latest ECMAScript features already.

Serve the production build

  • However, jest sometimes has to transform content from node_modules if that code uses ES6 import/export syntax.

  • In that case, use the transformIgnorePatterns option in jest.config.js.

    See the plugin's README for more information. Setting this to false can speed up production builds if you don't need source maps for production.

    • Default: undefined. Configure the crossorigin attribute on and