vuejs / vue-loader

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

vue-loader 17 compatibility with vue 2 #1919

Closed abea closed 2 years ago

abea commented 2 years ago

I'm attempting to bump from v15 to v17 on a Vue 2 project. I updated the require statement but get the error Error: Cannot find module 'vue/compiler-sfc' when running the build. I see some places there is a try catch to fall back to '@vue/compiler-sfc' when installed, but vue/compiler-sfc is still used elsewhere, which I understand is coming from Vue 3.

Is there a way I'm not seeing to use v17 with Vue 2? 15 is flagged by npm audit, blocking our normal CI flow.

vue-bot commented 2 years ago

Hello, thank you for taking time filling this issue!

However, we kindly ask you to use our Issue Helper when creating new issues, in order to ensure every issue provides the necessary information for us to investigate. This explains why your issue has been automatically closed by me (your robot friend!).

I hope to see your helper-created issue very soon!

hisuwh commented 2 years ago

I've hit this issue too. npm audit directed me to update vue-loader but now getting Error: Cannot find module 'vue/compiler-sfc'.

@abea did you solve this in your project?

abea commented 2 years ago

@hisuwh Not solved. It turns out vue-loader v16+ only supports Vue 3 (apparently, though it's not documented clearly). In v15 it could be resolved by updating the @vue/component-compiler-utils package, which someone has PR'd here: https://github.com/vuejs/component-compiler-utils/pull/121. If that PR merges this should be resolved.

leonheess commented 2 years ago

Why does it take this issue to find this absolutely essential information..

doubleaxe commented 1 year ago

For those, who are landing here or here googling why their vue v2.7 webpack build doesn't work with vue-loader v17. I found a way to make vue-loader v17 work with vue v2.7, actually it requires only a few code changes and can be done with (rather hacky) monkey patching.

It wasn't highly tested and for your own risk, but at least work for my components, vue v2.7.14 and vue-loader v17.2.2. Since I don't want this code to be lost, and don't know where is better to store it, I'll post it here. Order of imports and functions is important.

//trying to make working vue-loader@17
const compiler = require('@vue/compiler-sfc');

const _parse = compiler.parse;
compiler.parse = function(source, options) {
    const sfc = _parse({ source, ...options });
    //sfc.errors is warning list actually
    if(sfc.errors.length) {
        console.error(options.filename);
        sfc.errors.forEach((error) => console.error(error));
    }
    return {
        descriptor: sfc,
        errors: [],
    };
};
const _compileTemplate = compiler.compileTemplate;
compiler.compileTemplate = function(options) {
    const compiled = _compileTemplate(options);
    compiled.code += '\nexport {render, staticRenderFns};\n';
    return compiled;
};
//above works fine, but full support requires exporting staticRenderFns from compiled template
//this cannot be done right by simple monkey patching, only with source modifications
//but this simple function should work for most cases

const vueLoader = require('vue-loader');

const VueLoaderPlugin = vueLoader.VueLoaderPlugin;
const _loader = vueLoader.default;
vueLoader.default = function(source) {
    let compiled = _loader.call(this, source);
    const result = /import *{ *(?:ssrRender|render) *} *from ["']([^"']+)["']/.exec(compiled);
    if(result) {
        compiled = `\nimport { staticRenderFns } from '${result[1]}'\n` + compiled + '\n__exports__.staticRenderFns = staticRenderFns\n';
    }
    return compiled;
};