diff options
| author | ruki <waruqi@gmail.com> | 2018-11-08 00:38:48 +0800 |
|---|---|---|
| committer | ruki <waruqi@gmail.com> | 2018-11-07 21:53:09 +0800 |
| commit | 26105034da4fcce7ac883c899d781f016559310d (patch) | |
| tree | c459a5dc4e3aa0972d9919033ece511ce76dd129 /node_modules/vue-loader/lib/index.js | |
| parent | 2c77f00f1a7ecb6c8192f9c16d3b2001b254a107 (diff) | |
| download | xmake-docs-26105034da4fcce7ac883c899d781f016559310d.tar.gz xmake-docs-26105034da4fcce7ac883c899d781f016559310d.zip | |
switch to vuepress
Diffstat (limited to 'node_modules/vue-loader/lib/index.js')
| -rw-r--r-- | node_modules/vue-loader/lib/index.js | 193 |
1 files changed, 193 insertions, 0 deletions
diff --git a/node_modules/vue-loader/lib/index.js b/node_modules/vue-loader/lib/index.js new file mode 100644 index 00000000..752f9854 --- /dev/null +++ b/node_modules/vue-loader/lib/index.js @@ -0,0 +1,193 @@ +const path = require('path') +const hash = require('hash-sum') +const qs = require('querystring') +const plugin = require('./plugin') +const selectBlock = require('./select') +const loaderUtils = require('loader-utils') +const { attrsToQuery } = require('./codegen/utils') +const { parse } = require('@vue/component-compiler-utils') +const genStylesCode = require('./codegen/styleInjection') +const { genHotReloadCode } = require('./codegen/hotReload') +const genCustomBlocksCode = require('./codegen/customBlocks') +const componentNormalizerPath = require.resolve('./runtime/componentNormalizer') +const { NS } = require('./plugin') + +let errorEmitted = false + +function loadTemplateCompiler () { + try { + return require('vue-template-compiler') + } catch (e) { + throw new Error( + `[vue-loader] vue-template-compiler must be installed as a peer dependency, ` + + `or a compatible compiler implementation must be passed via options.` + ) + } +} + +module.exports = function (source) { + const loaderContext = this + + if (!errorEmitted && !loaderContext['thread-loader'] && !loaderContext[NS]) { + loaderContext.emitError(new Error( + `vue-loader was used without the corresponding plugin. ` + + `Make sure to include VueLoaderPlugin in your webpack config.` + )) + errorEmitted = true + } + + const stringifyRequest = r => loaderUtils.stringifyRequest(loaderContext, r) + + const { + target, + request, + minimize, + sourceMap, + rootContext, + resourcePath, + resourceQuery + } = loaderContext + + const rawQuery = resourceQuery.slice(1) + const inheritQuery = `&${rawQuery}` + const incomingQuery = qs.parse(rawQuery) + const options = loaderUtils.getOptions(loaderContext) || {} + + const isServer = target === 'node' + const isShadow = !!options.shadowMode + const isProduction = options.productionMode || minimize || process.env.NODE_ENV === 'production' + const filename = path.basename(resourcePath) + const context = rootContext || process.cwd() + const sourceRoot = path.dirname(path.relative(context, resourcePath)) + + const descriptor = parse({ + source, + compiler: options.compiler || loadTemplateCompiler(), + filename, + sourceRoot, + needMap: sourceMap + }) + + // if the query has a type field, this is a language block request + // e.g. foo.vue?type=template&id=xxxxx + // and we will return early + if (incomingQuery.type) { + return selectBlock( + descriptor, + loaderContext, + incomingQuery, + !!options.appendExtension + ) + } + + // module id for scoped CSS & hot-reload + const rawShortFilePath = path + .relative(context, resourcePath) + .replace(/^(\.\.[\/\\])+/, '') + + const shortFilePath = rawShortFilePath.replace(/\\/g, '/') + resourceQuery + + const id = hash( + isProduction + ? (shortFilePath + '\n' + source) + : shortFilePath + ) + + // feature information + const hasScoped = descriptor.styles.some(s => s.scoped) + const hasFunctional = descriptor.template && descriptor.template.attrs.functional + const needsHotReload = ( + !isServer && + !isProduction && + (descriptor.script || descriptor.template) && + options.hotReload !== false + ) + + // template + let templateImport = `var render, staticRenderFns` + let templateRequest + if (descriptor.template) { + const src = descriptor.template.src || resourcePath + const idQuery = `&id=${id}` + const scopedQuery = hasScoped ? `&scoped=true` : `` + const attrsQuery = attrsToQuery(descriptor.template.attrs) + const query = `?vue&type=template${idQuery}${scopedQuery}${attrsQuery}${inheritQuery}` + const request = templateRequest = stringifyRequest(src + query) + templateImport = `import { render, staticRenderFns } from ${request}` + } + + // script + let scriptImport = `var script = {}` + if (descriptor.script) { + const src = descriptor.script.src || resourcePath + const attrsQuery = attrsToQuery(descriptor.script.attrs, 'js') + const query = `?vue&type=script${attrsQuery}${inheritQuery}` + const request = stringifyRequest(src + query) + scriptImport = ( + `import script from ${request}\n` + + `export * from ${request}` // support named exports + ) + } + + // styles + let stylesCode = `` + if (descriptor.styles.length) { + stylesCode = genStylesCode( + loaderContext, + descriptor.styles, + id, + resourcePath, + stringifyRequest, + needsHotReload, + isServer || isShadow // needs explicit injection? + ) + } + + let code = ` +${templateImport} +${scriptImport} +${stylesCode} + +/* normalize component */ +import normalizer from ${stringifyRequest(`!${componentNormalizerPath}`)} +var component = normalizer( + script, + render, + staticRenderFns, + ${hasFunctional ? `true` : `false`}, + ${/injectStyles/.test(stylesCode) ? `injectStyles` : `null`}, + ${hasScoped ? JSON.stringify(id) : `null`}, + ${isServer ? JSON.stringify(hash(request)) : `null`} + ${isShadow ? `,true` : ``} +) + `.trim() + `\n` + + if (descriptor.customBlocks && descriptor.customBlocks.length) { + code += genCustomBlocksCode( + descriptor.customBlocks, + resourcePath, + resourceQuery, + stringifyRequest + ) + } + + if (needsHotReload) { + code += `\n` + genHotReloadCode(id, hasFunctional, templateRequest) + } + + // Expose filename. This is used by the devtools and Vue runtime warnings. + code += `\ncomponent.options.__file = ${ + isProduction + // For security reasons, only expose the file's basename in production. + ? JSON.stringify(filename) + // Expose the file's full path in development, so that it can be opened + // from the devtools. + : JSON.stringify(rawShortFilePath.replace(/\\/g, '/')) + }` + + code += `\nexport default component.exports` + // console.log(code) + return code +} + +module.exports.VueLoaderPlugin = plugin |
