1 | "use strict";
|
2 |
|
3 | var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
4 |
|
5 | var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
|
6 |
|
7 | const Asset = require('../Asset');
|
8 |
|
9 | const localRequire = require('../utils/localRequire');
|
10 |
|
11 | const md5 = require('../utils/md5');
|
12 |
|
13 | const _require = require('terser'),
|
14 | minify = _require.minify;
|
15 |
|
16 | const t = require('@babel/types');
|
17 |
|
18 | class VueAsset extends Asset {
|
19 | constructor(name, options) {
|
20 | super(name, options);
|
21 | this.type = 'js';
|
22 | }
|
23 |
|
24 | parse(code) {
|
25 | var _this = this;
|
26 |
|
27 | return (0, _asyncToGenerator2.default)(function* () {
|
28 |
|
29 | _this.vueTemplateCompiler = yield localRequire('vue-template-compiler', _this.name);
|
30 | _this.vue = yield localRequire('@vue/component-compiler-utils', _this.name);
|
31 | return _this.vue.parse({
|
32 | source: code,
|
33 | needMap: _this.options.sourceMaps,
|
34 | filename: _this.relativeName,
|
35 |
|
36 | sourceRoot: '',
|
37 |
|
38 | compiler: _this.vueTemplateCompiler
|
39 | });
|
40 | })();
|
41 | }
|
42 |
|
43 | generate() {
|
44 | var _this2 = this;
|
45 |
|
46 | return (0, _asyncToGenerator2.default)(function* () {
|
47 | let descriptor = _this2.ast;
|
48 | let parts = [];
|
49 |
|
50 | if (descriptor.script) {
|
51 | parts.push({
|
52 | type: descriptor.script.lang || 'js',
|
53 | value: descriptor.script.content,
|
54 | map: descriptor.script.map
|
55 | });
|
56 | }
|
57 |
|
58 | if (descriptor.template) {
|
59 | parts.push({
|
60 | type: descriptor.template.lang || 'html',
|
61 | value: descriptor.template.content.trim()
|
62 | });
|
63 | }
|
64 |
|
65 | if (descriptor.styles) {
|
66 | var _iteratorNormalCompletion = true;
|
67 | var _didIteratorError = false;
|
68 | var _iteratorError = undefined;
|
69 |
|
70 | try {
|
71 | for (var _iterator = descriptor.styles[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
|
72 | let style = _step.value;
|
73 | parts.push({
|
74 | type: style.lang || 'css',
|
75 | value: style.content.trim(),
|
76 | modules: !!style.module
|
77 | });
|
78 | }
|
79 | } catch (err) {
|
80 | _didIteratorError = true;
|
81 | _iteratorError = err;
|
82 | } finally {
|
83 | try {
|
84 | if (!_iteratorNormalCompletion && _iterator.return != null) {
|
85 | _iterator.return();
|
86 | }
|
87 | } finally {
|
88 | if (_didIteratorError) {
|
89 | throw _iteratorError;
|
90 | }
|
91 | }
|
92 | }
|
93 | }
|
94 |
|
95 | return parts;
|
96 | })();
|
97 | }
|
98 |
|
99 | postProcess(generated) {
|
100 | var _this3 = this;
|
101 |
|
102 | return (0, _asyncToGenerator2.default)(function* () {
|
103 | let result = [];
|
104 |
|
105 | let hasScoped = _this3.ast.styles.some(s => s.scoped);
|
106 |
|
107 | let id = md5(_this3.name).slice(-6);
|
108 | let scopeId = hasScoped ? `data-v-${id}` : null;
|
109 | let optsVar = '$' + id;
|
110 |
|
111 | let js = _this3.ast.script ? generated[0].value : '';
|
112 | let supplemental = '';
|
113 |
|
114 | if (_this3.options.scopeHoist) {
|
115 | optsVar = `$${t.toIdentifier(_this3.id)}$export$default`;
|
116 |
|
117 | if (!js.includes(optsVar)) {
|
118 | optsVar = `$${t.toIdentifier(_this3.id)}$exports`;
|
119 |
|
120 | if (!js.includes(optsVar)) {
|
121 | supplemental += `
|
122 | var ${optsVar} = {};
|
123 | `;
|
124 | _this3.cacheData.isCommonJS = true;
|
125 | }
|
126 | }
|
127 | } else {
|
128 | supplemental += `
|
129 | var ${optsVar} = exports.default || module.exports;
|
130 | `;
|
131 | }
|
132 |
|
133 | supplemental += `
|
134 | if (typeof ${optsVar} === 'function') {
|
135 | ${optsVar} = ${optsVar}.options;
|
136 | }
|
137 | `;
|
138 | supplemental += _this3.compileTemplate(generated, scopeId, optsVar);
|
139 | supplemental += _this3.compileCSSModules(generated, optsVar);
|
140 | supplemental += _this3.compileHMR(generated, optsVar);
|
141 |
|
142 | if (_this3.options.minify && !_this3.options.scopeHoist) {
|
143 | let _minify = minify(supplemental, {
|
144 | toplevel: true
|
145 | }),
|
146 | code = _minify.code,
|
147 | error = _minify.error;
|
148 |
|
149 | if (error) {
|
150 | throw error;
|
151 | }
|
152 |
|
153 | supplemental = code;
|
154 |
|
155 | if (supplemental) {
|
156 | supplemental = `\n(function(){${supplemental}})();`;
|
157 | }
|
158 | }
|
159 |
|
160 | js += supplemental;
|
161 |
|
162 | if (js) {
|
163 | result.push({
|
164 | type: 'js',
|
165 | value: js,
|
166 | map: _this3.options.sourceMaps && _this3.ast.script && generated[0].map
|
167 | });
|
168 | }
|
169 |
|
170 | let css = _this3.compileStyle(generated, scopeId);
|
171 |
|
172 | if (css) {
|
173 | result.push({
|
174 | type: 'css',
|
175 | value: css
|
176 | });
|
177 | }
|
178 |
|
179 | return result;
|
180 | })();
|
181 | }
|
182 |
|
183 | compileTemplate(generated, scopeId, optsVar) {
|
184 | let html = generated.find(r => r.type === 'html');
|
185 |
|
186 | if (html) {
|
187 | let isFunctional = this.ast.template.attrs.functional;
|
188 | let template = this.vue.compileTemplate({
|
189 | source: html.value,
|
190 | filename: this.relativeName,
|
191 | compiler: this.vueTemplateCompiler,
|
192 | isProduction: this.options.production,
|
193 | isFunctional,
|
194 | compilerOptions: {
|
195 | scopeId
|
196 | }
|
197 | });
|
198 |
|
199 | if (Array.isArray(template.errors) && template.errors.length >= 1) {
|
200 | throw new Error(template.errors[0]);
|
201 | }
|
202 |
|
203 | return `
|
204 | /* template */
|
205 | Object.assign(${optsVar}, (function () {
|
206 | ${template.code}
|
207 | return {
|
208 | render: render,
|
209 | staticRenderFns: staticRenderFns,
|
210 | _compiled: true,
|
211 | _scopeId: ${JSON.stringify(scopeId)},
|
212 | functional: ${JSON.stringify(isFunctional)}
|
213 | };
|
214 | })());
|
215 | `;
|
216 | }
|
217 |
|
218 | return '';
|
219 | }
|
220 |
|
221 | compileCSSModules(generated, optsVar) {
|
222 | let cssRenditions = generated.filter(r => r.type === 'css');
|
223 | let cssModulesCode = '';
|
224 | this.ast.styles.forEach((style, index) => {
|
225 | if (style.module) {
|
226 | let cssModules = JSON.stringify(cssRenditions[index].cssModules);
|
227 | let name = style.module === true ? '$style' : style.module;
|
228 | cssModulesCode += `\nthis[${JSON.stringify(name)}] = ${cssModules};`;
|
229 | }
|
230 | });
|
231 |
|
232 | if (cssModulesCode) {
|
233 | cssModulesCode = `function hook(){${cssModulesCode}\n}`;
|
234 | let isFunctional = this.ast.template && this.ast.template.attrs.functional;
|
235 |
|
236 | if (isFunctional) {
|
237 | return `
|
238 | /* css modules */
|
239 | (function () {
|
240 | ${cssModulesCode}
|
241 | ${optsVar}._injectStyles = hook;
|
242 | var originalRender = ${optsVar}.render;
|
243 | ${optsVar}.render = function (h, context) {
|
244 | hook.call(context);
|
245 | return originalRender(h, context);
|
246 | };
|
247 | })();
|
248 | `;
|
249 | } else {
|
250 | return `
|
251 | /* css modules */
|
252 | (function () {
|
253 | ${cssModulesCode}
|
254 | ${optsVar}.beforeCreate = ${optsVar}.beforeCreate ? ${optsVar}.beforeCreate.concat(hook) : [hook];
|
255 | })();
|
256 | `;
|
257 | }
|
258 | }
|
259 |
|
260 | return '';
|
261 | }
|
262 |
|
263 | compileStyle(generated, scopeId) {
|
264 | return generated.filter(r => r.type === 'css').reduce((p, r, i) => {
|
265 | let css = r.value;
|
266 | let scoped = this.ast.styles[i].scoped;
|
267 |
|
268 | if (scoped) {
|
269 | let _this$vue$compileStyl = this.vue.compileStyle({
|
270 | source: css,
|
271 | filename: this.relativeName,
|
272 | id: scopeId,
|
273 | scoped
|
274 | }),
|
275 | code = _this$vue$compileStyl.code,
|
276 | errors = _this$vue$compileStyl.errors;
|
277 |
|
278 | if (errors.length) {
|
279 | throw errors[0];
|
280 | }
|
281 |
|
282 | css = code;
|
283 | }
|
284 |
|
285 | return p + css;
|
286 | }, '');
|
287 | }
|
288 |
|
289 | compileHMR(generated, optsVar) {
|
290 | if (!this.options.hmr) {
|
291 | return '';
|
292 | }
|
293 |
|
294 | this.addDependency('vue-hot-reload-api');
|
295 | this.addDependency('vue');
|
296 | let cssHMR = '';
|
297 |
|
298 | if (this.ast.styles.length) {
|
299 | cssHMR = `
|
300 | var reloadCSS = require('_css_loader');
|
301 | module.hot.dispose(reloadCSS);
|
302 | module.hot.accept(reloadCSS);
|
303 | `;
|
304 | }
|
305 |
|
306 | let isFunctional = this.ast.template && this.ast.template.attrs.functional;
|
307 | return `
|
308 | /* hot reload */
|
309 | (function () {
|
310 | if (module.hot) {
|
311 | var api = require('vue-hot-reload-api');
|
312 | api.install(require('vue'));
|
313 | if (api.compatible) {
|
314 | module.hot.accept();
|
315 | if (!module.hot.data) {
|
316 | api.createRecord('${optsVar}', ${optsVar});
|
317 | } else {
|
318 | api.${isFunctional ? 'rerender' : 'reload'}('${optsVar}', ${optsVar});
|
319 | }
|
320 | }
|
321 |
|
322 | ${cssHMR}
|
323 | }
|
324 | })();`;
|
325 | }
|
326 |
|
327 | }
|
328 |
|
329 | module.exports = VueAsset; |
\ | No newline at end of file |