index.js 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. var loaderUtils = require('loader-utils')
  2. var normalize = require('../utils/normalize')
  3. var compiler = require('vue-template-compiler')
  4. var beautify = require('js-beautify').js_beautify
  5. var transpile = require('vue-template-es2015-compiler')
  6. var hotReloadAPIPath = normalize.dep('vue-hot-reload-api')
  7. var transformRequire = require('./modules/transform-require')
  8. module.exports = function (html) {
  9. this.cacheable()
  10. var isServer = this.target === 'node'
  11. var isProduction = this.minimize || process.env.NODE_ENV === 'production'
  12. var vueOptions = this.options.__vueOptions__ || {}
  13. var options = loaderUtils.getOptions(this) || {}
  14. var defaultModules = [transformRequire(options.transformToRequire)]
  15. var userModules = vueOptions.compilerModules || options.compilerModules
  16. // for HappyPack cross-process use cases
  17. if (typeof userModules === 'string') {
  18. userModules = require(userModules)
  19. }
  20. var compilerOptions = {
  21. preserveWhitespace: options.preserveWhitespace,
  22. modules: defaultModules.concat(userModules || [])
  23. }
  24. var compiled = compiler.compile(html, compilerOptions)
  25. // tips
  26. if (compiled.tips && compiled.tips.length) {
  27. compiled.tips.forEach(tip => {
  28. this.emitWarning(tip)
  29. })
  30. }
  31. var code
  32. if (compiled.errors && compiled.errors.length) {
  33. this.emitError(
  34. `\n Error compiling template:\n${pad(html)}\n` +
  35. compiled.errors.map(e => ` - ${e}`).join('\n') + '\n'
  36. )
  37. code = 'module.exports={render:function(){},staticRenderFns:[]}'
  38. } else {
  39. var bubleOptions = options.buble
  40. code = transpile('module.exports={' +
  41. 'render:' + toFunction(compiled.render) + ',' +
  42. 'staticRenderFns: [' + compiled.staticRenderFns.map(toFunction).join(',') + ']' +
  43. '}', bubleOptions)
  44. // mark with stripped (this enables Vue to use correct runtime proxy detection)
  45. if (!isProduction && (
  46. !bubleOptions ||
  47. !bubleOptions.transforms ||
  48. bubleOptions.transforms.stripWith !== false
  49. )) {
  50. code += `\nmodule.exports.render._withStripped = true`
  51. }
  52. }
  53. // hot-reload
  54. if (!isServer && !isProduction) {
  55. code +=
  56. '\nif (module.hot) {\n' +
  57. ' module.hot.accept()\n' +
  58. ' if (module.hot.data) {\n' +
  59. ' require("' + hotReloadAPIPath + '").rerender("' + options.id + '", module.exports)\n' +
  60. ' }\n' +
  61. '}'
  62. }
  63. return code
  64. }
  65. function toFunction (code) {
  66. return 'function (){' + beautify(code, {
  67. indent_size: 2 // eslint-disable-line camelcase
  68. }) + '}'
  69. }
  70. function pad (html) {
  71. return html.split(/\r?\n/).map(line => ` ${line}`).join('\n')
  72. }