vuejs / vue-loader

📦 Webpack loader for Vue.js components
MIT License
4.99k stars 915 forks source link

[Question] Any loader hook provided before compile? #2039

Open kenken17 opened 1 year ago

kenken17 commented 1 year ago

Hi, I am new to tap into the world of loader (webpack), may i know if the latest vue-loader have any lifecycle hooks (like preTransformNode previously) that I can tap into before the AST tree is being compiled? I need to manipulate some nodes for my usage.

I have quickly browser the source code but cant seems to find any. So I created a loader to run before vue-loader myself to make use of compileTemplte from @vue/compilet-sfc, but I is there any way I can transform it back to string template to pass to vue-loader?

Any guidance would be greatly appreciated. :)

RaphaelDDL commented 1 year ago

Interestingly, I had the same need last week and I wasn't able to do much, as you said yourself, the const compiler = require('vue/compiler-sfc'); compiler.parse(source,options) doesn't seem to have a toString or something to get it back after you make modifications to the object.

So what I did was the opposite, I intercepted the source before passing it to Vue. So, in your webpack ruleset you might have something like this, right:

      {
        test: /\.vue$/,
        loader: 'vue-loader',
      },

What I did was add another test for vue below it (webpack rule order go from last to first) and change the source before it goes to vue-loader, by running "my loader". Webpack requires loaders to have external files, so to avoid having to make my own, having to config aliases, etc etc, I instead am using simple-functional-loader and in this way, I can drop a function in the webpack config directly.

So an example:

const { createLoader } = require('simple-functional-loader');

module.exports = {
  module: {
    rules: [
      // (...other rules...)
      {
        test: /\.vue$/,
        loader: 'vue-loader',
      },
      {
        test: /\.vue$/,
        use: createLoader(function(source, map) {
            // here, received `source` is the entire .vue file, as a string
            // `this` has a loader context, such as resourcePath, etc
            // do whatever you want to do with the string then remember to return 
            // a string at the end, this will go to vue-loader to be parsed
            return myEditedString
          }),
      },
      // (...other rules...)
}

The caveat is that I don't have access to pretty parsed arrays like sfc's parse gives, split into style, script, template and having attributes list. So I had to work with RegExp directly on the string, which is not the best and very error prone if not tested properly, but is what I could come with as vue-loader has no pre-parse hook.

Let me know if you find anything better than this lol.

kenken17 commented 1 year ago

Hi @RaphaelDDL. Thanks for the reply. I am actually doing the same (as running a custom loader before vue-loader), yet I am still using the compiler-sfc to get the AST because I have the same exact reason as you, which is not to mess with regexp cause it's too much hassle and error-prone. I dont have any better/worse solution but I am now looking at migrating from webpack to vite. Hope can get some easy way out. Finger crossed.