Skip to content

Commit c954f32

Browse files
committed
feat: handle <template lang="xxx"> with loaders
BREAKING CHANGE: <template lang="xxx"> are now handled with webpack loaders as well.
1 parent 144cc7c commit c954f32

15 files changed

+173
-17
lines changed

Diff for: README.md

+45
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,50 @@ The benefit is that this same rule also applies to plain `*.less` imports from J
8888

8989
v15 also allows using non-serializable options for loaders, which was not possible in previous versions.
9090

91+
### Template Preprocessing
92+
93+
v14 and below uses [consolidate](https://github.com/tj/consolidate.js/) to compile `<template lang="xxx">`. v15 now applies preprocessing for them using webpack loaders instead.
94+
95+
Note that some template loaders such as `pug-loader` exports a compiled templating function instead of plain HTML. In order to pass the correct content to Vue's template compiler, you must use a loader that outputs plain HTML instead. For example, to support `<template lang="pug">`, you can use [pug-plain-loader](https://github.com/yyx990803/pug-plain-loader):
96+
97+
``` js
98+
{
99+
module: {
100+
rules: [
101+
{
102+
test: /\.pug$/,
103+
loader: 'pug-plain-loader'
104+
}
105+
]
106+
}
107+
}
108+
```
109+
110+
If you also intend to use it to import .pug files as HTML strings in JavaScript, you will need to chain `raw-loader` after the preprocessing loader. Note however adding raw-loader would break the usage in Vue components, so you need to have two rules, one of them excluding Vue components:
111+
112+
``` js
113+
{
114+
module: {
115+
rules: [
116+
{
117+
test: /\.pug$/,
118+
oneOf: [
119+
// this applies to <template lang="pug"> in Vue components
120+
{
121+
resourceQuery: /^\?vue/,
122+
use: ['pug-plain-loader']
123+
},
124+
// this applies to pug imports inside JavaScript
125+
{
126+
use: ['raw-loader', 'pug-plain-loader']
127+
}
128+
]
129+
}
130+
]
131+
}
132+
}
133+
```
134+
91135
### Style Injection
92136

93137
Client-side style injection now injects all styles upfront to ensure consistent behavior between development and extracted mode.
@@ -200,6 +244,7 @@ The following options have been deprecated and should be configured using normal
200244
- `cssSourceMap`
201245
- `buble`
202246
- `extractCSS`
247+
- `template`
203248

204249
The following options have been deprecated and should be configured using the new `compilerOptions` option:
205250

Diff for: example/debugger.js

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module.exports = function (...args) {
2+
this.callback(null, ...args)
3+
}
4+
5+
module.exports.pitch = function (request) {
6+
// debug
7+
}

Diff for: example/source.vue

+3-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
<template>
2-
<div>
3-
<h1 :class="$style.red">{{ msg }}</h1>
4-
</div>
1+
<template lang="pug">
2+
div(ok)
3+
h1(:class="$style.red") hello
54
</template>
65

76
<script>

Diff for: example/test.pug

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
div(ok)
2+
h1(:class="$style.red") hello

Diff for: example/webpack.config.js

+25-7
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,37 @@ module.exports = {
1515
},
1616
module: {
1717
rules: [
18+
// { loader: require.resolve('./debugger') },
1819
{
1920
test: /\.vue$/,
2021
loader: 'vue-loader'
2122
},
23+
// example to apply loader to a custom block without lang="xxx"
24+
// this rule applies to <foo> blocks
2225
{
2326
resourceQuery: /blockType=foo/,
2427
loader: 'babel-loader'
2528
},
29+
// example configuring preprocessor for <template lang="pug">
30+
{
31+
test: /\.pug$/,
32+
oneOf: [
33+
// this applies to <template lang="pug"> in Vue components
34+
{
35+
resourceQuery: /^\?vue/,
36+
use: ['pug-plain-loader']
37+
},
38+
// this applies to pug imports inside JavaScript
39+
{
40+
use: ['raw-loader', 'pug-plain-loader']
41+
}
42+
]
43+
},
44+
// example configuring CSS Modules
2645
{
2746
test: /\.css$/,
2847
oneOf: [
48+
// this applies to <style module>
2949
{
3050
resourceQuery: /module/,
3151
use: [
@@ -39,6 +59,7 @@ module.exports = {
3959
}
4060
]
4161
},
62+
// this applies to <style> or <style scoped>
4263
{
4364
use: [
4465
'vue-style-loader',
@@ -47,19 +68,16 @@ module.exports = {
4768
}
4869
]
4970
},
71+
// exmaple configration for <style lang="scss">
5072
{
5173
test: /\.scss$/,
5274
use: [
5375
'vue-style-loader',
54-
{
55-
loader: 'css-loader',
56-
options: {
57-
modules: true,
58-
localIdentName: '[local]_[hash:base64:8]'
59-
}
60-
},
76+
'css-loader',
6177
{
6278
loader: 'sass-loader',
79+
// global data for all components
80+
// this can be read from a scss file
6381
options: {
6482
data: '$color: red;'
6583
}

Diff for: lib/loaders/templateLoader.js

-3
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,6 @@ module.exports = function (source) {
3434
filename: this.resourcePath,
3535
compiler,
3636
compilerOptions,
37-
// handle possible lang="xxx"
38-
preprocessLang: query.lang,
39-
preprocessOptions: options.template,
4037
// allow customizing behavior of vue-template-es2015-compiler
4138
transpileOptions: options.transpileOptions,
4239
transformAssetUrls: options.transformAssetUrls || true,

Diff for: package.json

+1
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
"normalize-newline": "^3.0.0",
6161
"postcss-loader": "^2.1.2",
6262
"pug": "^2.0.1",
63+
"pug-plain-loader": "^1.0.0",
6364
"raw-loader": "^0.5.1",
6465
"sass-loader": "^6.0.7",
6566
"stylus": "^0.54.5",

Diff for: test/core.spec.js

+26-2
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,15 @@ test('pre-processors', done => {
3434
module: {
3535
rules: [
3636
{
37-
test: /\.js/,
37+
test: /\.js$/,
3838
loader: 'babel-loader'
3939
},
4040
{
41-
test: /\.stylus/,
41+
test: /\.pug$/,
42+
loader: 'pug-plain-loader'
43+
},
44+
{
45+
test: /\.stylus$/,
4246
use: [
4347
'vue-style-loader',
4448
'css-loader',
@@ -112,6 +116,26 @@ test('template import', done => {
112116
})
113117
})
114118

119+
test('template import with pre-processors', done => {
120+
mockBundleAndRun({
121+
entry: 'template-import-pre.vue',
122+
module: {
123+
rules: [
124+
{
125+
test: /\.pug$/,
126+
loader: 'pug-plain-loader'
127+
}
128+
]
129+
}
130+
}, ({ window, module }) => {
131+
const vnode = mockRender(module)
132+
// '<div><h1>hello</h1></div>'
133+
expect(vnode.children[0].tag).toBe('h1')
134+
expect(vnode.children[0].children[0].text).toBe('hello')
135+
done()
136+
})
137+
})
138+
115139
test('script import', done => {
116140
mockBundleAndRun({
117141
entry: 'script-import.vue'

Diff for: test/fixtures/template-import-pre.vue

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<template lang="pug" src="./template-import.pug"></template>

Diff for: test/fixtures/template-import.html

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<div>
2+
<h1>hello</h1>
3+
</div>

Diff for: test/fixtures/template-import.vue

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
<template lang="pug" src="./template-import.pug"></template>
1+
<template src="./template-import.html"></template>

Diff for: test/fixtures/template-pre.js

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import Comp1 from './template-pre.vue'
2+
import Comp2 from './template-import-pre.vue'
3+
import html from './template-import.pug'
4+
5+
window.exports = {
6+
Comp1,
7+
Comp2,
8+
html
9+
}

Diff for: test/fixtures/template-pre.vue

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<template lang="pug">
2+
div
3+
h1 hello
4+
</template>

Diff for: test/template.spec.js

+40
Original file line numberDiff line numberDiff line change
@@ -252,3 +252,43 @@ test('custom compiler directives', done => {
252252
done()
253253
})
254254
})
255+
256+
test('separate loader configuration for template lang and js imports', done => {
257+
mockBundleAndRun({
258+
entry: './test/fixtures/template-pre.js',
259+
module: {
260+
rules: [
261+
{
262+
test: /\.pug$/,
263+
oneOf: [
264+
// this applies to <template lang="pug"> in Vue components
265+
{
266+
resourceQuery: /^\?vue/,
267+
use: ['pug-plain-loader']
268+
},
269+
// this applies to pug imports inside JavaScript
270+
{
271+
use: ['raw-loader', 'pug-plain-loader']
272+
}
273+
]
274+
}
275+
]
276+
}
277+
}, ({ exports }) => {
278+
function assertRender (vnode) {
279+
expect(vnode.tag).toBe('div')
280+
expect(vnode.children[0].tag).toBe('h1')
281+
expect(vnode.children[0].children[0].text).toBe('hello')
282+
}
283+
284+
// <template lang="pug">
285+
const vnode1 = mockRender(exports.Comp1, {})
286+
assertRender(vnode1)
287+
// <template lang="pug" src="./foo.pug">
288+
const vnode2 = mockRender(exports.Comp2, {})
289+
assertRender(vnode2)
290+
// import html from './foo.pug'
291+
expect(exports.html).toBe('<div><h1>hello</h1></div>')
292+
done()
293+
})
294+
})

Diff for: yarn.lock

+6
Original file line numberDiff line numberDiff line change
@@ -6646,6 +6646,12 @@ pug-parser@^5.0.0:
66466646
pug-error "^1.3.2"
66476647
token-stream "0.0.1"
66486648

6649+
pug-plain-loader@^1.0.0:
6650+
version "1.0.0"
6651+
resolved "https://registry.yarnpkg.com/pug-plain-loader/-/pug-plain-loader-1.0.0.tgz#cef2a984c90251882109ec2d417a6b433aa6b42a"
6652+
dependencies:
6653+
loader-utils "^1.1.0"
6654+
66496655
pug-runtime@^2.0.4:
66506656
version "2.0.4"
66516657
resolved "https://registry.yarnpkg.com/pug-runtime/-/pug-runtime-2.0.4.tgz#e178e1bda68ab2e8c0acfc9bced2c54fd88ceb58"

0 commit comments

Comments
 (0)