vue-loader-v16 v16.0.0-beta.5.4
vue-loader
webpack loader for Vue Single-File Components
Attention
Non-official publishment, just for private learning, resource comes from official vue-loader's next branch, release is v16.0.0-beta.5.
Why I Use My vue-loader-v16
For Vue 3?
The npm version made it. But now the reason has gone.
The command to upgrade NPM is:
npm i -g npm
Yes, now you just need to upgrade npm version,and then run npm run serve
will be ok.
In vue official README.md, it syas:
As of v4.5.0, use @vue/cli
built-in option to choose Vue 3 preset when creating a vue 3 project, like this:
vue create <your vue 3 project name>
So when you start a vue 3 project by cli command, you need it, upgrade npm at first.
My experience is:
When I start a vue 3 project vuenext-vuecli-vite
, but it failed. The reason told me it depend on a module: vue-loader-v16
, then I publish it on npm
from official resource vue-loader
's branch next
, lastest release tag
is v16.0.0-beta.5. But now I realize that the error caused by npm low version. Older npm cannot understand the config:
{"vue-loader-v16": "npm:vue-loader@^16.0.0-beta.3}
,
so the folder vue-loader-v16
dependency module cannot be created, but new npm provides the function. Now my npm is v6.14.8
.
What is Vue Loader?
vue-loader
is a loader for webpack that allows you to author Vue components in a format called Single-File Components (SFCs):
<template>
<div class="example">{{ msg }}</div>
</template>
<script>
export default {
data () {
return {
msg: 'Hello world!'
}
}
}
</script>
<style>
.example {
color: red;
}
</style>
There are many cool features provided by vue-loader
:
- Allows using other webpack loaders for each part of a Vue component, for example Sass for
<style>
and Pug for<template>
; - Allows custom blocks in a
.vue
file that can have custom loader chains applied to them; - Treat static assets referenced in
<style>
and<template>
as module dependencies and handle them with webpack loaders; - Simulate scoped CSS for each component;
- State-preserving hot-reloading during development.
In a nutshell, the combination of webpack and vue-loader
gives you a modern, flexible and extremely powerful front-end workflow for authoring Vue.js applications.
How It Works
The following section is for maintainers and contributors who are interested in the internal implementation details of
vue-loader
, and is not required knowledge for end users.
vue-loader
is not a simple source transform loader. It handles each language blocks inside an SFC with its own dedicated loader chain (you can think of each block as a "virtual module"), and finally assembles the blocks together into the final module. Here's a brief overview of how the whole thing works:
vue-loader
parses the SFC source code into an SFC Descriptor using@vue/compiler-sfc
. It then generates an import for each language block so the actual returned module code looks like this:// code returned from the main loader for 'source.vue' // import the <template> block import render from 'source.vue?vue&type=template' // import the <script> block import script from 'source.vue?vue&type=script' export * from 'source.vue?vue&type=script' // import <style> blocks import 'source.vue?vue&type=style&index=1' script.render = render export default script
Notice how the code is importing
source.vue
itself, but with different request queries for each block.We want the content in
script
block to be treated like.js
files (and if it's<script lang="ts">
, we want to to be treated like.ts
files). Same for other language blocks. So we want webpack to apply any configured module rules that matches.js
also to requests that look likesource.vue?vue&type=script
. This is whatVueLoaderPlugin
(src/plugins.ts
) does: for each module rule in the webpack config, it creates a modified clone that targets corresponding Vue language block requests.Suppose we have configured
babel-loader
for all*.js
files. That rule will be cloned and applied to Vue SFC<script>
blocks as well. Internally to webpack, a request likeimport script from 'source.vue?vue&type=script'
Will expand to:
import script from 'babel-loader!vue-loader!source.vue?vue&type=script'
Notice the
vue-loader
is also matched becausevue-loader
are applied to.vue
files.Similarly, if you have configured
style-loader
+css-loader
+sass-loader
for*.scss
files:<style scoped lang="scss">
Will be returned by
vue-loader
as:import 'source.vue?vue&type=style&index=1&scoped&lang=scss'
And webpack will expand it to:
import 'style-loader!css-loader!sass-loader!vue-loader!source.vue?vue&type=style&index=1&scoped&lang=scss'
When processing the expanded requests, the main
vue-loader
will get invoked again. This time though, the loader notices that the request has queries and is targeting a specific block only. So it selects (src/select.ts
) the inner content of the target block and passes it on to the loaders matched after it.For the
<script>
block, this is pretty much it. For<template>
and<style>
blocks though, a few extra tasks need to be performed:- We need to compile the template using the Vue template compiler;
- We need to post-process the CSS in
<style scoped>
blocks, aftercss-loader
but beforestyle-loader
.
Technically, these are additional loaders (
src/templateLoader.ts
andsrc/stylePostLoader.ts
) that need to be injected into the expanded loader chain. It would be very complicated if the end users have to configure this themselves, soVueLoaderPlugin
also injects a global Pitching Loader (src/pitcher.ts
) that intercepts Vue<template>
and<style>
requests and injects the necessary loaders. The final requests look like the following:// <template lang="pug"> import 'vue-loader/template-loader!pug-loader!source.vue?vue&type=template' // <style scoped lang="scss"> import 'style-loader!vue-loader/style-post-loader!css-loader!sass-loader!vue-loader!source.vue?vue&type=style&index=1&scoped&lang=scss'
Maybe Issues
As running npm install --production
to install production dependency modules, the ./src
files throw none import syntax. But if I use @vue/cli
4.5+ to create a vue app, after installed, it works well without errors.
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago