webpack loader for Vue Single-File Components

17.4.2 · active · verified Sun Apr 19

vue-loader is the essential webpack loader for building Vue.js applications using Single-File Components (SFCs). It enables webpack to parse `.vue` files, allowing developers to structure their components with separate `<template>`, `<script>`, and `<style>` blocks, each of which can leverage other webpack loaders (e.g., Sass for styles, Pug for templates, TypeScript for scripts). The current stable version is 17.4.2, which primarily targets Vue 3 and webpack 5, though it retains some compatibility with webpack 4. The project maintains an active release cadence, frequently publishing bug fixes and feature enhancements. Key differentiators include its deep integration with the Vue SFC specification, providing features like scoped CSS, custom blocks, efficient asset handling, and state-preserving hot-reloading for an optimized development experience, making it an indispensable part of most Vue CLI and custom webpack setups.

Common errors

Warnings

Install

Imports

Quickstart

This quickstart demonstrates a basic webpack setup with vue-loader for a Vue 3 application using TypeScript. It includes a `webpack.config.js` with rules for .vue, .ts, and .css files, the required `VueLoaderPlugin`, a simple `App.vue` Single-File Component with `<script lang="ts">`, a `main.ts` entry point, global CSS, and an `index.html` to load the bundled output, showcasing how to compile and run a minimal Vue project.

/* webpack.config.js */
import { VueLoaderPlugin } from 'vue-loader';
import path from 'path';

export default {
  mode: 'development',
  entry: './src/main.ts',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js',
  },
  module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader',
      },
      {
        test: /\.ts$/,
        loader: 'ts-loader',
        options: {
          appendTsSuffixTo: [require.resolve('./src/App.vue')], // Path to main vue component or [/\.vue$/]
        },
        exclude: /node_modules/,
      },
      {
        test: /\.css$/,
        use: [
          'vue-style-loader',
          'css-loader',
        ],
      },
    ],
  },
  plugins: [
    new VueLoaderPlugin(),
  ],
  resolve: {
    extensions: ['.vue', '.js', '.ts'],
  },
  devServer: {
    static: {
      directory: path.join(__dirname, 'public'),
    },
    compress: true,
    port: 8080,
    hot: true,
  },
};

/* src/main.ts */
import { createApp } from 'vue';
import App from './App.vue';
import './assets/main.css';

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

<!-- src/App.vue -->
<template>
  <div class="container">
    <h1>{{ greeting }}</h1>
    <p>This is a Vue Single-File Component processed by vue-loader.</p>
    <button @click="increment">Count: {{ count }}</button>
  </div>
</template>

<script lang="ts">
import { defineComponent, ref } from 'vue';

export default defineComponent({
  name: 'App',
  setup() {
    const greeting = ref('Hello, vue-loader!');
    const count = ref(0);

    const increment = () => {
      count.value++;
    };

    return {
      greeting,
      count,
      increment,
    };
  },
});
</script>

<style scoped>
.container {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
  border: 1px solid #ddd;
  padding: 20px;
  border-radius: 8px;
  max-width: 600px;
  margin-left: auto;
  margin-right: auto;
}

h1 {
  color: #42b983;
}

button {
  background-color: #42b983;
  color: white;
  border: none;
  padding: 10px 20px;
  border-radius: 5px;
  cursor: pointer;
  font-size: 16px;
  margin-top: 15px;
}

button:hover {
  background-color: #368a6f;
}
</style>

/* src/assets/main.css */
body {
  margin: 0;
  padding: 0;
  background-color: #f4f4f4;
}

<!-- public/index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Vue Loader Quickstart</title>
</head>
<body>
  <div id="app"></div>
  <script src="bundle.js"></script>
</body>
</html>

view raw JSON →