Vue-loader: VueLoaderPlugin causes loaders to run several times

Created on 1 May 2018  路  5Comments  路  Source: vuejs/vue-loader

Version

15.0.0

Reproduction link

https://github.com/killerDJO/vue-loader-minimal

Steps to reproduce

Prererquisites:

  • ts-loader is used and has options specified (Important!).
  • SFC with referenced TypeScript file is used.

Run webpack build using mentioned configuration. Rules might look like this:

module: {
    rules: [
        {
            test: /\.ts$/,
            loader: "ts-loader",
            options: {},
            exclude: [/node_modules/]
        },
        {
            test: /\.vue$/,
            loader: "vue-loader",
        }
    ]
},
resolve: {
    extensions: [".ts"],
},
plugins: [
    new VueLoaderPlugin()
],

What is expected?

Build is finished successfully.

What is actually happening?

Build failed.


In the current implementation VueLoaderPlugin clones webpack rules and modifies them to run on .vue files. However, this leads to an issues when a file is referenced from .vue component (e. g. <script src="./App.ts" lang="ts"></script>). In this case the file can be matched by two rules (original and cloned) and ts-loader will be executed two times, with second time executing using output of the first run.
This will happend only if "options" object is specified, because otherwise webpack will use a single loader for two rules (VueLoaderPlugin removes "options" during rules cloning, so only original rule will have options).

Aforementioned behaviour has been observed for ts-loader, but is likely to occur for scss/sass loaders as well.

bug

All 5 comments

This might be the very thing I've run into while upgrading from webpack@3+vue-loader@14 to webpack@4+vue-loader@15. I suddenly get oodles of TypeScript errors, most of which are issues of the form of "Parameter 'something' implicitly has 'any' type". I suspect a "double run" because many of the errors reported have non-sensical line numbers (they don't match up to anything in the actual source files).

Any workarounds I could test to verify this?

Okay, just commented out the ts-loader's options object like so:

{
    test: /\.ts$/,
    loader: 'ts-loader',
    exclude: /node_modules/,
    // options: {
    //     appendTsSuffixTo:[/\.vue$/]
    // }
}

All the errors I was receiving disappeared and compilation appeared to wrap up without issue. This seems like a pretty serious problem.

For the record, I also use the "external source file" method outlined in the initial report.

@ericdrobinson
This is exactly the issue I ran into. For me it also worked when I removed options from loader.
Another workaround I can imagine (if options are neccessary) is to modify 'test' parameter, e.g. it can check only for files which are outside of vue components folder (in this case these files will be compiled only by cloned ts-loader, which has own test).

We place .ts files next to .vue files... Does the vue-loader simply append .ts to the end of .vue files? If so, you could exclude .vue.ts...

Unfortunately, it doesn't work exactly like this, so .vue.ts cannot be used. It is possible to use resourceQuery or issuer to check for .ts files imported from .vue files, but in this case it will fail for other (non-vue) ts files (entry file will not have an issuer and usual ts files will not have a resourceQuery, so webpack will fail such rules since it doesn't support checks for an empty value). It might be possible to get this to work using some tricks, but it's much simpler to just remove options for now.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

chrisvfritz picture chrisvfritz  路  4Comments

matt-sanders picture matt-sanders  路  4Comments

flashios09 picture flashios09  路  3Comments

TheVexatious picture TheVexatious  路  3Comments

yozman picture yozman  路  4Comments