Description
Background
Recently I'm experimenting with feature toggles (feature flags) within Vue.js. It is fairly easy to implement for JavaScript code with webpack's DefinePlugin
and UglifyJSPlugin
, but when it comes to templates in .vue
files, it is a little bit tricky.
What I have in mind is to preprocess the .vue
files and remove some markup in the <template>
block before sending it to vue-loader
so that I can dictate what's included in the final build. As an example, say I have the following vue component:
<template>
<div>
<on feature="AWESOME_FEATURE">
Awesome feature is here!
</on>
<off feature="AWESOME_FEATURE">
If awesome feature is not released yet, I will be shown.
</off>
</div>
</template>
And I have my AWESOME_FEATURE
feature toggle set to false
, I would like to preprocess the template and send the following code to vue-loader
:
<template>
<div>
If awesome feature is not released yet, I will be shown.
</div>
</template>
I have tried to chain my preprocessing loader before vue-loader
like the following (in webpack config):
...
module: {
loaders: [
{
test: /\.vue$/,
loader: 'vue!vue-features'
}
]
}
...
However, this does not work. I then verified that my vue-features-loader
does pass the correct content to vue-loader
, and vue-loader
indeed received the corrent content, but the final build code does not seem to be affected.
When I looked at the source code of vue-loader
, I found that what it does is just generating a require
statement for each part of the vue
file and using a selector
module to read directly from the vue
file. So loaders sitting in between the source file and vue-loader
cannot really do their jobs as expected, because the generate require statement does not reference them.
The Impact
This problem impacts all scenarios where any sort of preprocessing needs to be done on the .vue
source files.
Although we can use the vue.loaders
config to swap out the default loaders entirely and replace them with custom loaders, but this is not trivial, and not necessary in most cases.
Proposed Solutions
A possible solution to this problem would be to pass content selected with the selector
module to those loaders falling in between the source file and vue-loader
.
Another solution might be allowing users to specify extra loaders to preprocess each part of the vue
file. (This is not to replace the default loaders via the vue.loaders
config, but to add in additional loaders to do preprocessing, and still pass the output to the default loaders)