Skip to content

Commit 7b37fa9

Browse files
committed
add dependency injection feature
1 parent 72c0ab4 commit 7b37fa9

File tree

5 files changed

+76
-27
lines changed

5 files changed

+76
-27
lines changed

lib/loader.js

Lines changed: 44 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ module.exports = function (content) {
2727
var self = this
2828
this.cacheable()
2929
var cb = this.async()
30-
var output = ''
3130
var options = this.options.vue || {}
31+
var query = loaderUtils.parseQuery(this.query)
3232
var vueUrl = loaderUtils.getRemainingRequest(this)
3333
var filePath = this.resourcePath
3434
var fileName = path.basename(filePath)
@@ -80,6 +80,7 @@ module.exports = function (content) {
8080
var lang = part.lang || defaultLang[type]
8181
var loader = loaders[lang]
8282
var rewriter = getRewriter(type, scoped)
83+
var injectString = (type === 'script' && query.inject) ? 'inject!' : ''
8384
if (loader !== undefined) {
8485
// inject rewriter before css/html loader for
8586
// extractTextPlugin use cases
@@ -90,7 +91,7 @@ module.exports = function (content) {
9091
} else {
9192
loader = ensureBang(loader) + rewriter
9293
}
93-
return ensureBang(loader)
94+
return injectString + ensureBang(loader)
9495
} else {
9596
// unknown lang, assume a loader for it is used
9697
switch (type) {
@@ -99,7 +100,7 @@ module.exports = function (content) {
99100
case 'style':
100101
return 'style!css!' + rewriter + lang + '!'
101102
case 'script':
102-
return lang + '!'
103+
return injectString + lang + '!'
103104
}
104105
}
105106
}
@@ -139,6 +140,7 @@ module.exports = function (content) {
139140
// which is an object that contains info about the vue file.
140141
var parts = self.exec(source, url)
141142
var hasLocalStyles = false
143+
var output = 'var __vue_script__, __vue_template__\n'
142144

143145
// add requires for src imports
144146
parts.styleImports.forEach(function (impt) {
@@ -157,46 +159,61 @@ module.exports = function (content) {
157159
if (parts.script.length) {
158160
script = parts.script[0]
159161
output +=
160-
'module.exports = ' + (
162+
'__vue_script__ = ' + (
161163
script.src
162164
? getRequireForImport('script', script, 0)
163165
: getRequire('script', script, 0)
164-
) + '\nif (module.exports.__esModule) module.exports = module.exports.default\n'
166+
)
165167
}
166168

167169
// add require for template
168170
var template
169171
if (parts.template.length) {
170172
template = parts.template[0]
171-
output += ';(typeof module.exports === "function" ' +
172-
'? module.exports.options ' +
173-
': module.exports).template = ' + (
173+
output += '__vue_template__ = ' + (
174174
template.src
175175
? getRequireForImport('template', template, hasLocalStyles)
176176
: getRequire('template', template, 0, hasLocalStyles)
177177
)
178178
}
179179

180-
// hot reload
181-
if (
182-
process.env.NODE_ENV !== 'production' &&
183-
(parts.script.length || parts.template.length)
184-
) {
180+
if (!query.inject) {
181+
// attach template
182+
output +=
183+
'module.exports = __vue_script__ || {}\n' +
184+
'if (module.exports.__esModule) module.exports = module.exports.default\n' +
185+
';(typeof module.exports === "function" ? module.exports.options : module.exports).template = __vue_template__\n'
186+
// hot reload
187+
if (
188+
process.env.NODE_ENV !== 'production' &&
189+
(parts.script.length || parts.template.length)
190+
) {
191+
output +=
192+
'if (module.hot) {(function () {' +
193+
' module.hot.accept()\n' +
194+
' var hotAPI = require("vue-hot-reload-api")\n' +
195+
' hotAPI.install(require("vue"), true)\n' +
196+
' if (!hotAPI.compatible) return\n' +
197+
' var id = ' + JSON.stringify(filePath) + '\n' +
198+
' if (!module.hot.data) {\n' +
199+
// initial insert
200+
' hotAPI.createRecord(id, module.exports)\n' +
201+
' } else {\n' +
202+
// update
203+
' hotAPI.update(id, module.exports, __vue_template__)\n' +
204+
' }\n' +
205+
'})()}'
206+
}
207+
} else {
185208
output +=
186-
'if (module.hot) {(function () {' +
187-
' module.hot.accept()\n' +
188-
' var hotAPI = require("vue-hot-reload-api")\n' +
189-
' hotAPI.install(require("vue"), true)\n' +
190-
' if (!hotAPI.compatible) return\n' +
191-
' var id = ' + JSON.stringify(filePath) + '\n' +
192-
' if (!module.hot.data) {\n' +
193-
// initial insert
194-
' hotAPI.createRecord(id, module.exports)\n' +
195-
' } else {\n' +
196-
// update
197-
' hotAPI.update(id, module.exports, (typeof module.exports === "function" ? module.exports.options : module.exports).template)\n' +
198-
' }\n' +
199-
'})()}'
209+
'module.exports = function (injections) {\n' +
210+
' var mod = __vue_script__\n' +
211+
' ? __vue_script__(injections)\n' +
212+
' : {}\n' +
213+
' if (mod.__esModule) mod = mod.default\n' +
214+
' ;(typeof mod === "function" ? mod.options : mod).template = __vue_template__\n' +
215+
' return mod\n' +
216+
'}'
200217
}
201218

202219
// done

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
"css-loader": "^0.21.0",
5959
"eslint": "^1.6.0",
6060
"extract-text-webpack-plugin": "^0.8.2",
61+
"inject-loader": "^2.0.1",
6162
"jade": "^1.11.0",
6263
"jsdom": "^6.5.1",
6364
"mkdirp": "^0.5.1",

test/fixtures/inject.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
window.injector = require('!!vue?inject!./inject.vue')

test/fixtures/inject.vue

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<template>
2+
<div class="msg">{{ msg }}</div>
3+
</template>
4+
5+
<script>
6+
import SomeService from '../service'
7+
8+
export default {
9+
data () {
10+
return {
11+
msg: SomeService.msg
12+
}
13+
}
14+
}
15+
</script>

test/test.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,4 +211,19 @@ describe('vue-loader', function () {
211211
})
212212
})
213213

214+
it('dependency injection', function () {
215+
test({
216+
entry: './test/fixtures/inject.js'
217+
}, function (window) {
218+
var module = window.injector({
219+
'../service': {
220+
msg: 'Hello from mocked service!'
221+
}
222+
})
223+
expect(module.template).to.contain('<div class="msg">{{ msg }}</div>')
224+
expect(module.data().msg).to.contain('Hello from mocked service!')
225+
done()
226+
})
227+
})
228+
214229
})

0 commit comments

Comments
 (0)