Install & Compatibility
Where this runs
tested against v? · npm install
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslnode 18–226 runs
build_error
glibcnode 18–226 runs
build_error
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
VueLoaderPlugin
✓ import { VueLoaderPlugin } from 'vue-loader';
✗ const VueLoaderPlugin = require('vue-loader').VueLoaderPlugin;
The VueLoaderPlugin is essential for processing SFCs; it must be instantiated in your webpack config's plugins array. CommonJS `require` works, but ESM `import` is preferred for modern webpack setups.
Rule for .vue files
✓ { test: /\.vue$/, loader: 'vue-loader' }
✗ { test: /\.vue$/, use: ['vue-loader'] }
While 'use' array technically works, 'loader' property is a direct shorthand when only one loader is applied. Ensure this rule comes before other loaders that might process specific language blocks within the SFC (e.g., ts-loader, sass-loader).
TypeScript support
✓ { test: /\.ts$/, loader: 'ts-loader', options: { appendTsSuffixTo: [/\.vue$/] } }
✗ No specific `wrong` for this, but omitting `appendTsSuffixTo` can lead to issues.
When using TypeScript within `<script lang="ts">` blocks in SFCs, ensure ts-loader (or esbuild-loader) is configured to process these files. The `appendTsSuffixTo: [/\.vue$/]` option in `ts-loader` is crucial for it to recognize and compile TypeScript inside .vue files.
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>
Errors
Common errors & fixes
Module parse failed: Unexpected token (1:0) You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file.
Webpack encountered a `.vue` file but does not have a rule configured to use `vue-loader` for it.
fixAdd a rule to your `webpack.config.js` `module.rules` array: `{ test: /\.vue$/, loader: 'vue-loader' }`. TypeError: VueLoaderPlugin is not a constructor
The `VueLoaderPlugin` was either imported incorrectly (e.g., as a default import when it's a named export) or instantiated without the `new` keyword.
fixEnsure you `import { VueLoaderPlugin } from 'vue-loader';` and use `new VueLoaderPlugin()` in your `webpack.config.js` plugins array. Error: [vue-loader] vue-loader currently only supports Vue 2. If you are using Vue 3, you should use vue-loader@^16.0.0 instead.
You are attempting to use an older version of `vue-loader` (v15 or earlier) with a Vue 3 project.
fixUpgrade `vue-loader` to version 16 or newer (e.g., `npm install vue-loader@latest --save-dev`).
[vue-loader] vue-loader requires @vue/compiler-sfc (since v16) to be installed.
Your `vue-loader` version (v16+) requires the `@vue/compiler-sfc` package, which is missing from your project dependencies.
fixInstall `@vue/compiler-sfc`: `npm install @vue/compiler-sfc --save-dev`.
Audit
Dependencies
webpackrequiredRequired peer dependency as vue-loader is a webpack loader.