diff options
Diffstat (limited to 'node_modules/vue-loader/lib/loaders')
| -rw-r--r-- | node_modules/vue-loader/lib/loaders/pitcher.js | 144 | ||||
| -rw-r--r-- | node_modules/vue-loader/lib/loaders/stylePostLoader.js | 23 | ||||
| -rw-r--r-- | node_modules/vue-loader/lib/loaders/templateLoader.js | 71 |
3 files changed, 238 insertions, 0 deletions
diff --git a/node_modules/vue-loader/lib/loaders/pitcher.js b/node_modules/vue-loader/lib/loaders/pitcher.js new file mode 100644 index 00000000..0bc77046 --- /dev/null +++ b/node_modules/vue-loader/lib/loaders/pitcher.js @@ -0,0 +1,144 @@ +const qs = require('querystring') +const loaderUtils = require('loader-utils') +const hash = require('hash-sum') +const selfPath = require.resolve('../index') +const templateLoaderPath = require.resolve('./templateLoader') +const stylePostLoaderPath = require.resolve('./stylePostLoader') + +const isESLintLoader = l => /(\/|\\|@)eslint-loader/.test(l.path) +const isNullLoader = l => /(\/|\\|@)null-loader/.test(l.path) +const isCSSLoader = l => /(\/|\\|@)css-loader/.test(l.path) +const isPitcher = l => l.path !== __filename + +const dedupeESLintLoader = loaders => { + const res = [] + let seen = false + loaders.forEach(l => { + if (!isESLintLoader(l)) { + res.push(l) + } else if (!seen) { + seen = true + res.push(l) + } + }) + return res +} + +module.exports = code => code + +// This pitching loader is responsible for intercepting all vue block requests +// and transform it into appropriate requests. +module.exports.pitch = function (remainingRequest) { + const options = loaderUtils.getOptions(this) + const { cacheDirectory, cacheIdentifier } = options + const query = qs.parse(this.resourceQuery.slice(1)) + + let loaders = this.loaders + + // if this is a language block request, eslint-loader may get matched + // multiple times + if (query.type) { + // if this is an inline block, since the whole file itself is being linted, + // remove eslint-loader to avoid duplicate linting. + if (/\.vue$/.test(this.resourcePath)) { + loaders = loaders.filter(l => !isESLintLoader(l)) + } else { + // This is a src import. Just make sure there's not more than 1 instance + // of eslint present. + loaders = dedupeESLintLoader(loaders) + } + } + + // remove self + loaders = loaders.filter(isPitcher) + + // do not inject if user uses null-loader to void the type (#1239) + if (loaders.some(isNullLoader)) { + return + } + + const genRequest = loaders => { + // Important: dedupe since both the original rule + // and the cloned rule would match a source import request. + // also make sure to dedupe based on loader path. + // assumes you'd probably never want to apply the same loader on the same + // file twice. + // Exception: in Vue CLI we do need two instances of postcss-loader + // for user config and inline minification. So we need to dedupe baesd on + // path AND query to be safe. + const seen = new Map() + const loaderStrings = [] + + loaders.forEach(loader => { + const identifier = typeof loader === 'string' + ? loader + : (loader.path + loader.query) + const request = typeof loader === 'string' ? loader : loader.request + if (!seen.has(identifier)) { + seen.set(identifier, true) + // loader.request contains both the resolved loader path and its options + // query (e.g. ??ref-0) + loaderStrings.push(request) + } + }) + + return loaderUtils.stringifyRequest(this, '-!' + [ + ...loaderStrings, + this.resourcePath + this.resourceQuery + ].join('!')) + } + + // Inject style-post-loader before css-loader for scoped CSS and trimming + if (query.type === `style`) { + const cssLoaderIndex = loaders.findIndex(isCSSLoader) + if (cssLoaderIndex > -1) { + const afterLoaders = loaders.slice(0, cssLoaderIndex + 1) + const beforeLoaders = loaders.slice(cssLoaderIndex + 1) + const request = genRequest([ + ...afterLoaders, + stylePostLoaderPath, + ...beforeLoaders + ]) + // console.log(request) + return `import mod from ${request}; export default mod; export * from ${request}` + } + } + + // for templates: inject the template compiler & optional cache + if (query.type === `template`) { + const path = require('path') + const cacheLoader = cacheDirectory && cacheIdentifier + ? [`cache-loader?${JSON.stringify({ + // For some reason, webpack fails to generate consistent hash if we + // use absolute paths here, even though the path is only used in a + // comment. For now we have to ensure cacheDirectory is a relative path. + cacheDirectory: path.isAbsolute(cacheDirectory) + ? path.relative(process.cwd(), cacheDirectory) + : cacheDirectory, + cacheIdentifier: hash(cacheIdentifier) + '-vue-loader-template' + })}`] + : [] + const request = genRequest([ + ...cacheLoader, + templateLoaderPath + `??vue-loader-options`, + ...loaders + ]) + // console.log(request) + // the template compiler uses esm exports + return `export * from ${request}` + } + + // if a custom block has no other matching loader other than vue-loader itself, + // we should ignore it + if (query.type === `custom` && + loaders.length === 1 && + loaders[0].path === selfPath) { + return `` + } + + // When the user defines a rule that has only resourceQuery but no test, + // both that rule and the cloned rule will match, resulting in duplicated + // loaders. Therefore it is necessary to perform a dedupe here. + const request = genRequest(loaders) + return `import mod from ${request}; export default mod; export * from ${request}` +} diff --git a/node_modules/vue-loader/lib/loaders/stylePostLoader.js b/node_modules/vue-loader/lib/loaders/stylePostLoader.js new file mode 100644 index 00000000..de8d09eb --- /dev/null +++ b/node_modules/vue-loader/lib/loaders/stylePostLoader.js @@ -0,0 +1,23 @@ +const qs = require('querystring') +const { compileStyle } = require('@vue/component-compiler-utils') + +// This is a post loader that handles scoped CSS transforms. +// Injected right before css-loader by the global pitcher (../pitch.js) +// for any <style scoped> selection requests initiated from within vue files. +module.exports = function (source, inMap) { + const query = qs.parse(this.resourceQuery.slice(1)) + const { code, map, errors } = compileStyle({ + source, + filename: this.resourcePath, + id: `data-v-${query.id}`, + map: inMap, + scoped: !!query.scoped, + trim: true + }) + + if (errors.length) { + this.callback(errors[0]) + } else { + this.callback(null, code, map) + } +} diff --git a/node_modules/vue-loader/lib/loaders/templateLoader.js b/node_modules/vue-loader/lib/loaders/templateLoader.js new file mode 100644 index 00000000..d5b18741 --- /dev/null +++ b/node_modules/vue-loader/lib/loaders/templateLoader.js @@ -0,0 +1,71 @@ +const qs = require('querystring') +const loaderUtils = require('loader-utils') +const { compileTemplate } = require('@vue/component-compiler-utils') + +// Loader that compiles raw template into JavaScript functions. +// This is injected by the global pitcher (../pitch) for template +// selection requests initiated from vue files. +module.exports = function (source) { + const loaderContext = this + const query = qs.parse(this.resourceQuery.slice(1)) + + // although this is not the main vue-loader, we can get access to the same + // vue-loader options because we've set an ident in the plugin and used that + // ident to create the request for this loader in the pitcher. + const options = loaderUtils.getOptions(loaderContext) || {} + const { id } = query + const isServer = loaderContext.target === 'node' + const isProduction = loaderContext.minimize || process.env.NODE_ENV === 'production' + const isFunctional = query.functional + + // allow using custom compiler via options + const compiler = options.compiler || require('vue-template-compiler') + const compilerOptions = Object.assign({}, options.compilerOptions, { + scopeId: query.scoped ? `data-v-${id}` : null, + comments: query.comments + }) + + // for vue-component-compiler + const finalOptions = { + source, + filename: this.resourcePath, + compiler, + compilerOptions, + // allow customizing behavior of vue-template-es2015-compiler + transpileOptions: options.transpileOptions, + transformAssetUrls: options.transformAssetUrls || true, + isProduction, + isFunctional, + optimizeSSR: isServer && options.optimizeSSR !== false + } + + const compiled = compileTemplate(finalOptions) + + // tips + if (compiled.tips && compiled.tips.length) { + compiled.tips.forEach(tip => { + loaderContext.emitWarning(tip) + }) + } + + // errors + if (compiled.errors && compiled.errors.length) { + loaderContext.emitError( + `\n Error compiling template:\n${pad(compiled.source)}\n` + + compiled.errors.map(e => ` - ${e}`).join('\n') + + '\n' + ) + } + + const { code } = compiled + + // finish with ESM exports + return code + `\nexport { render, staticRenderFns }` +} + +function pad (source) { + return source + .split(/\r?\n/) + .map(line => ` ${line}`) + .join('\n') +} |
