DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • How To Use IBM App Connect To Build Flows
  • Vue.js Tutorial: Build a Tesla Battery Range Calculator in Vue 3
  • MLOps: How to Build a Toolkit to Boost AI Project Performance
  • Stateless vs. Stateful Widgets: Make the Right Choice for Your Flutter App

Trending

  • Why High-Performance AI/ML Is Essential in Modern Cybersecurity
  • A Deep Dive Into Firmware Over the Air for IoT Devices
  • Top Book Picks for Site Reliability Engineers
  • Intro to RAG: Foundations of Retrieval Augmented Generation, Part 1
  1. DZone
  2. Coding
  3. JavaScript
  4. 4 Ways To Boost Your Vue.js App With Webpack

4 Ways To Boost Your Vue.js App With Webpack

If you're looking to give your Vue.js-based web application a little bit of an enhancement, read on to see how Webpack can help with that.

By 
Anthony Gore user avatar
Anthony Gore
DZone Core CORE ·
Updated Feb. 10, 20 · Tutorial
Likes (3)
Comment
Save
Tweet
Share
18.6K Views

Join the DZone community and get the full member experience.

Join For Free

webpack is an essential tool for developing vue.js single page applications. it makes your development workflow much simpler by managing complex build steps and can optimize your app's size and performance.

in this article, i'll explain four ways that webpack can enhance your vue app, including:

  1. single file components.
  2. optimizing the vue build.
  3. browser cache management.
  4. code splitting.

what about vue-cli?

if you're using a template to build your app from vue-cli , a pre-made webpack config is provided. they're well optimized and there are no improvements i can suggest!

but since they work so well out of the box, you probably don't have much idea of what they're really doing, right? consider this article an overview of the webpack config used in the vue-cli templates, as they include the same optimizations i'm discussing here.

1. single file components

one of vue's idiosyncratic features is the use of html for component templates. these come with an intrinsic problem, though: either your html markup needs to be in an awkward javascript string, or your template and component definition will need to be in separate files, making them hard to work with.

vue has an elegant solution called single file components (sfcs) that include the template, component definition, and css all in one neat .vue file:

mycomponent.vue

<template>
  <div id="my-component">...</div>
</template>
<script>
  export default {...}
</script>
<style>
  #my-component {...}
</style>

sfcs are made possible by the vue-loader webpack plugin. this loader splits up the sfcs language blocks and pipes each to an appropriate loader, e.g. the script block goes to babel-loader , while the template block goes to vue's own vue-template-loader which transforms the template into a javascript render function.

the final output of vue-loader is a javascript module ready for inclusion in your webpack bundle.

a typical configuration for vue-loader is as follows:

module: {
  rules: [
    {
      test: /\.vue$/,
      loader: 'vue-loader',
      options: {
        loaders: {
          // override the default loaders
        }
      }
    },
  ]
}

2. optimizing the vue build

runtime-only build

if you're only using render functions in your vue app*, and no html templates, you don't need vue's template compiler. you can reduce your bundle size by omitting the compiler from the webpack build.

* remember that single file component templates are pre-compiled in development to render functions!

there is a runtime-only build of the vue.js library that includes all the features of vue.js except the template compiler, called vue.runtime.js . it's about 20kb smaller than the full build so it's worth using if you can.

the runtime-only build is used by default, so every time you use import vue from 'vue'; in your project that's what you'll get. you can change to a different build, though, by using the alias configuration option:

resolve: {
  alias: {
    'vue$': 'vue/dist/vue.esm.js' // use the full build
  }
},

stripping out warnings and error messages in production

another way to reduce your vue.js build size is to remove any error messages and warnings in production. these bloat your output bundle size with unnecessary code and also incur a runtime cost you're best to avoid.

if you inspect the vue source code you'll see that warning blocks are conditional on the value of an environment variable process.env.node_env e.g.:

if (process.env.node_env !== 'production') {
  warn(("error in " + info + ": \"" + (err.tostring()) + "\""), vm);
}

if process.env.node_env is set to production then such warning blocks can be automatically stripped out of the code by a minifier during the build process.

you can use the defineplugin to set the value of process.env.node_env , and the uglifyjsplugin to minify the code and strip out the unused blocks:

if (process.env.node_env === 'production') {
  module.exports.plugins = (module.exports.plugins || []).concat([
    new webpack.defineplugin({
      'process.env': {
        node_env: '"production"'
      }
    }),
    new webpack.optimize.uglifyjsplugin()
  ])
}

3. browser cache management

a user's browser will cache your site's files so that they'll only download if the browser does not already have a local copy, or if the local copy has expired.

if all your code is in one file, then a tiny change would mean the whole file would need to be re-downloaded. ideally, you want your users to download as little as possible, so it'd be smart to separate your app's rarely changing code from its frequently changing code.

vendor file

the common chunks plugin can decouple your vendor code (e.g. dependencies like the vue.js library that are unlikely to change very often) from your application code (code that may change on every deployment).

you can configure the plugin to check if a dependency is from the node_modules folder, and if so, output it into a separate file vendor.js :

new webpack.optimize.commonschunkplugin({
  name: 'vendor',
  minchunks: function (module) {
    return module.context && module.context.indexof('node_modules') !== -1;
  }
})

if you do this, you'll now have two separate files in your build output which will be cached by the browser independently:

<script src="vendor.js" charset="utf-8"></script>
<script src="app.js" charset="utf-8"></script>

fingerprinting

when a build file changes, how do we bust a browser's cache?

by default, only when a cached file expires, or when the user manually clears the cache, will the browser request the file again from the server. the file will be re-downloaded if the server indicates the file has changed (otherwise the server returns http 304 not modified).

to save an unnecessary server request, we can change a file's name every time its content changes to force the browser to re-download it. a simple system for doing this is to add a "fingerprint" to the file name by appending a hash, e.g.:

image title

the common chunks plugin emits a "chunkhash" which is updated if the file's content has changed. webpack can append this hash to the file names when they're outputted:

output: {
  filename: '[name].[chunkhash].js'
},

when you do this, you'll see that your outputted files will have names like app.3b80b7c17398c31e4705.js .

auto inject build files

of course, if you add a hash, you'll have to update the reference to the file in your index file, otherwise, the browser won't know about it:

<script src="app.3b80b7c17398c31e4705.js"></script>

this would be a hugely tedious task to do manually, so use the html webpack plugin to do it for you. this plugin can auto inject references to the build files into your html file in the bundling process.

start by removing references to your build file:

index.html

<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <title>test-6</title>
  </head>
  <body>
    <div id="app"></div>
    <!-- built files should go here, but will be auto injected -->
  </body>
</html>

and add the html webpack plugin to your webpack config:

new htmlwebpackplugin({
  filename: 'index.html'
  template: 'index.html',
  inject: true,
  chunkssortmode: 'dependency'
}),

now your build files with hashes will automatically be added to your index file. also, your index.html file will now be included in your bundle output so you may need to tell the web server that its location has changed.

4. code splitting

by default, webpack will output all your app's code into one large bundle. but if your app has multiple pages, it would be more efficient to split the code so each individual page's code is in a separate file, and is only loaded when needed.

webpack has a feature called "code splitting" that does exactly that. achieving this in vue.js also requires async components , and is made even easier with vue router .

async components

rather than having a definition object as their second argument, async components have a promise function that resolves the definition object, for example:

vue.component('async-component', function (resolve, reject) {
  settimeout(() => {
    resolve({
      // component definition including props, methods etc.
    });
  }, 1000)
})

vue will only call the function when the component actually needs to be rendered. it will also cache the result for future re-renders.

if we architect our app so each "page" is a component, and we store the definition on our server, then we're halfway to achieving code splitting.

require

to load your async component's code from the server, use the webpack require syntax. this will instruct webpack to bundle async-component in a separate bundle when it builds, and better yet, webpack will handle the loading of this bundle with ajax, so your code can be as simple as this:

vue.component('async-component', function (resolve) {
  require(['./asynccomponent.vue'], resolve)
});

lazy loading

in a vue.js app, vue-router will typically be the module you use to organize your spa into multiple pages. lazy loading is a formalized way to achieve code splitting with vue and webpack.

const homepage = resolve => require(['./homepage.vue'], resolve);

const rounter = new vuerouter({
  routes: [
    {
      path: '/',
      name: 'homepage',
      component: homepage
    }
  ]
})
app Vue.js Build (game engine) Template Boost (C++ libraries)

Published at DZone with permission of Anthony Gore, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • How To Use IBM App Connect To Build Flows
  • Vue.js Tutorial: Build a Tesla Battery Range Calculator in Vue 3
  • MLOps: How to Build a Toolkit to Boost AI Project Performance
  • Stateless vs. Stateful Widgets: Make the Right Choice for Your Flutter App

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!