Skip to content

Commit 37329e1

Browse files
committed
fix: duplicate loaders when using src import with loader options
close #1278
1 parent 56cd3d1 commit 37329e1

File tree

7 files changed

+99
-12
lines changed

7 files changed

+99
-12
lines changed

lib/loaders/pitcher.js

+23-11
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,26 @@ module.exports.pitch = function (remainingRequest) {
1717
return
1818
}
1919

20-
// loader.request contains both the resolved loader path and its options
21-
// query (e.g. ??ref-0)
22-
const toLoaderString = loader => loader.request
20+
const genRequest = loaders => {
21+
// Important: dedupe since both the original rule
22+
// and the cloned rule would match a source import request.
23+
// also make sure to dedupe based on loader path.
24+
// assumes you'd probably never want to apply the same loader on the same
25+
// file twice.
26+
const seen = new Map()
27+
const loaderStrings = []
28+
29+
loaders.forEach(loader => {
30+
const type = typeof loader === 'string' ? loader : loader.path
31+
const request = typeof loader === 'string' ? loader : loader.request
32+
if (!seen.has(type)) {
33+
seen.set(type, true)
34+
// loader.request contains both the resolved loader path and its options
35+
// query (e.g. ??ref-0)
36+
loaderStrings.push(request)
37+
}
38+
})
2339

24-
const genRequest = loaderStrings => {
25-
// important: dedupe
26-
loaderStrings = Array.from(new Set(loaderStrings))
2740
return loaderUtils.stringifyRequest(this, '-!' + [
2841
...loaderStrings,
2942
this.resourcePath + this.resourceQuery
@@ -34,8 +47,8 @@ module.exports.pitch = function (remainingRequest) {
3447
if (query.type === `style`) {
3548
const cssLoaderIndex = loaders.findIndex(l => /(\/|\\)css-loader/.test(l.path))
3649
if (cssLoaderIndex) {
37-
const afterLoaders = loaders.slice(0, cssLoaderIndex + 1).map(toLoaderString)
38-
const beforeLoaders = loaders.slice(cssLoaderIndex + 1).map(toLoaderString)
50+
const afterLoaders = loaders.slice(0, cssLoaderIndex + 1)
51+
const beforeLoaders = loaders.slice(cssLoaderIndex + 1)
3952
const request = genRequest([
4053
...afterLoaders,
4154
stylePostLoaderPath,
@@ -48,10 +61,9 @@ module.exports.pitch = function (remainingRequest) {
4861

4962
// for templates: inject the template compiler
5063
if (query.type === `template`) {
51-
const beforeLoaders = loaders.map(toLoaderString)
5264
const request = genRequest([
5365
templateLoaderPath + `??vue-loader-options`,
54-
...beforeLoaders
66+
...loaders
5567
])
5668
// console.log(request)
5769
// the template compiler uses esm exports
@@ -69,6 +81,6 @@ module.exports.pitch = function (remainingRequest) {
6981
// When the user defines a rule that has only resourceQuery but no test,
7082
// both that rule and the cloned rule will match, resulting in duplicated
7183
// loaders. Therefore it is necessary to perform a dedupe here.
72-
const request = genRequest(loaders.map(toLoaderString))
84+
const request = genRequest(loaders)
7385
return `import mod from ${request}; export default mod; export * from ${request}`
7486
}

package.json

+2
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@
7070
"stylus": "^0.54.5",
7171
"stylus-loader": "^3.0.2",
7272
"sugarss": "^1.0.1",
73+
"ts-loader": "^4.2.0",
74+
"typescript": "^2.8.3",
7375
"url-loader": "^1.0.1",
7476
"vue": "^2.5.16",
7577
"vue-server-renderer": "^2.5.16",

test/edgeCases.spec.js

+22
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ const {
1010
} = require('./utils')
1111

1212
const assertComponent = ({ window, module }, done) => {
13+
if (typeof module === 'function') {
14+
module = module.options
15+
}
16+
1317
const vnode = mockRender(module, {
1418
msg: 'hi'
1519
})
@@ -162,3 +166,21 @@ test('usage with null-loader', done => {
162166
done()
163167
})
164168
})
169+
170+
test('proper dedupe on src-imports with options', done => {
171+
mockBundleAndRun({
172+
entry: 'ts.vue',
173+
resolve: {
174+
extensions: ['.ts', '.js']
175+
},
176+
module: {
177+
rules: [
178+
{
179+
test: /\.ts$/,
180+
loader: 'ts-loader',
181+
options: { appendTsSuffixTo: [/\.vue$/] }
182+
}
183+
]
184+
}
185+
}, res => assertComponent(res, done))
186+
})

test/fixtures/App.ts

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import Vue from 'vue'
2+
3+
export default Vue.extend({
4+
data () {
5+
return {
6+
msg: 'Hello from Component A!'
7+
}
8+
},
9+
methods: {
10+
someMethod (arg: string): string {
11+
return 'hello'
12+
}
13+
}
14+
})

test/fixtures/ts.vue

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<template>
2+
<h2 class="red">{{ msg }}</h2>
3+
</template>
4+
5+
<script src="./App.ts" lang="ts"></script>
6+
7+
<style>
8+
comp-a h2 {
9+
color: #f00;
10+
}
11+
</style>

tsconfig.json

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"compilerOptions": {
3+
"module": "esnext",
4+
"moduleResolution": "node",
5+
"strict": true,
6+
"target": "es6",
7+
"baseUrl": "."
8+
},
9+
"exclude": [
10+
"node_modules"
11+
]
12+
}

yarn.lock

+15-1
Original file line numberDiff line numberDiff line change
@@ -8293,7 +8293,7 @@ semver-diff@^2.0.0:
82938293
dependencies:
82948294
semver "^5.0.3"
82958295

8296-
"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0:
8296+
"semver@2 || 3 || 4 || 5", semver@^5.0.1, semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0:
82978297
version "5.5.0"
82988298
resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab"
82998299

@@ -9164,6 +9164,16 @@ trim-right@^1.0.1:
91649164
dependencies:
91659165
glob "^6.0.4"
91669166

9167+
ts-loader@^4.2.0:
9168+
version "4.2.0"
9169+
resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-4.2.0.tgz#c380c399fc81f82cad0e3044f9c1f775ecde6efa"
9170+
dependencies:
9171+
chalk "^2.3.0"
9172+
enhanced-resolve "^4.0.0"
9173+
loader-utils "^1.0.2"
9174+
micromatch "^3.1.4"
9175+
semver "^5.0.1"
9176+
91679177
91689178
version "0.0.0"
91699179
resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6"
@@ -9199,6 +9209,10 @@ typedarray@^0.0.6:
91999209
version "0.0.6"
92009210
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
92019211

9212+
typescript@^2.8.3:
9213+
version "2.8.3"
9214+
resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.8.3.tgz#5d817f9b6f31bb871835f4edf0089f21abe6c170"
9215+
92029216
uc.micro@^1.0.1, uc.micro@^1.0.5:
92039217
version "1.0.5"
92049218
resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.5.tgz#0c65f15f815aa08b560a61ce8b4db7ffc3f45376"

0 commit comments

Comments
 (0)