123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119 |
- const prettier = require('prettier')
- const loaderUtils = require('loader-utils')
- const normalize = require('../utils/normalize')
- const compiler = require('vue-template-compiler')
- const transpile = require('vue-template-es2015-compiler')
- const hotReloadAPIPath = normalize.dep('vue-hot-reload-api')
- const transformRequire = require('./modules/transform-require')
- const transformSrcset = require('./modules/transform-srcset')
- module.exports = function (html) {
- this.cacheable()
- const isServer = this.target === 'node'
- const isProduction = this.minimize || process.env.NODE_ENV === 'production'
- const vueOptions = this.options.__vueOptions__ || {}
- const options = loaderUtils.getOptions(this) || {}
- const needsHotReload = !isServer && !isProduction && vueOptions.hotReload !== false
- const defaultModules = [transformRequire(options.transformToRequire), transformSrcset()]
- let userModules = vueOptions.compilerModules || options.compilerModules
- // for HappyPack cross-process use cases
- if (typeof userModules === 'string') {
- userModules = require(userModules)
- }
- const compilerOptions = {
- preserveWhitespace: options.preserveWhitespace,
- modules: defaultModules.concat(userModules || []),
- directives:
- vueOptions.compilerDirectives || options.compilerDirectives || {},
- scopeId: options.hasScoped ? options.id : null,
- comments: options.hasComment
- }
- const compile =
- isServer && compiler.ssrCompile && vueOptions.optimizeSSR !== false
- ? compiler.ssrCompile
- : compiler.compile
- const compiled = compile(html, compilerOptions)
- // tips
- if (compiled.tips && compiled.tips.length) {
- compiled.tips.forEach(tip => {
- this.emitWarning(tip)
- })
- }
- let code
- if (compiled.errors && compiled.errors.length) {
- this.emitError(
- `\n Error compiling template:\n${pad(html)}\n` +
- compiled.errors.map(e => ` - ${e}`).join('\n') +
- '\n'
- )
- code = vueOptions.esModule
- ? `var esExports = {render:function(){},staticRenderFns: []}\nexport default esExports`
- : 'module.exports={render:function(){},staticRenderFns:[]}'
- } else {
- const bubleOptions = options.buble
- const stripWith = bubleOptions.transforms.stripWith !== false
- const stripWithFunctional = bubleOptions.transforms.stripWithFunctional
- const staticRenderFns = compiled.staticRenderFns.map(fn =>
- toFunction(fn, stripWithFunctional)
- )
- code =
- transpile(
- 'var render = ' +
- toFunction(compiled.render, stripWithFunctional) +
- '\n' +
- 'var staticRenderFns = [' +
- staticRenderFns.join(',') +
- ']',
- bubleOptions
- ) + '\n'
- // prettify render fn
- if (!isProduction) {
- code = prettier.format(code, { semi: false, parser: 'babylon' })
- }
- // mark with stripped (this enables Vue to use correct runtime proxy detection)
- if (!isProduction && stripWith) {
- code += `render._withStripped = true\n`
- }
- const exports = `{ render: render, staticRenderFns: staticRenderFns }`
- code += vueOptions.esModule
- ? `var esExports = ${exports}\nexport default esExports`
- : `module.exports = ${exports}`
- }
- // hot-reload
- if (needsHotReload) {
- const exportsName = vueOptions.esModule ? 'esExports' : 'module.exports'
- code +=
- '\nif (module.hot) {\n' +
- ' module.hot.accept()\n' +
- ' if (module.hot.data) {\n' +
- ' require("' + hotReloadAPIPath + '")' +
- ' .rerender("' + options.id + '", ' + exportsName + ')\n' +
- ' }\n' +
- '}'
- }
- return code
- }
- function toFunction (code, stripWithFunctional) {
- return (
- 'function (' + (stripWithFunctional ? '_h,_vm' : '') + ') {' + code + '}'
- )
- }
- function pad (html) {
- return html
- .split(/\r?\n/)
- .map(line => ` ${line}`)
- .join('\n')
- }
|