vue-loader
Advanced tools
Comparing version 15.10.2 to 15.11.0
@@ -0,1 +1,9 @@ | ||
<a name="15.10.2"></a> | ||
# [15.10.2](https://github.com/vuejs/vue-loader/compare/v15.10.1...v15.10.2) (2023-08-23) | ||
### Bug Fixes | ||
* don't enable prettify by default if prettier 3 is detected ([aa2558d](https://github.com/vuejs/vue-loader/commit/aa2558d)) | ||
<a name="15.10.1"></a> | ||
@@ -2,0 +10,0 @@ # [15.10.1](https://github.com/vuejs/vue-loader/compare/v15.10.0...v15.10.1) (2022-11-14) |
const qs = require('querystring') | ||
const { attrsToQuery } = require('./utils') | ||
const { attrsToQuery, genMatchResource } = require('./utils') | ||
module.exports = function genCustomBlocksCode( | ||
loaderContext, | ||
blocks, | ||
resourcePath, | ||
resourceQuery, | ||
stringifyRequest | ||
stringifyRequest, | ||
enableInlineMatchResource | ||
) { | ||
@@ -20,7 +22,18 @@ return ( | ||
const inheritQuery = resourceQuery ? `&${resourceQuery.slice(1)}` : '' | ||
const externalQuery = block.attrs.src ? `&external` : `` | ||
const query = `?vue&type=custom&index=${i}&blockType=${qs.escape( | ||
block.type | ||
)}${issuerQuery}${attrsQuery}${inheritQuery}` | ||
)}${issuerQuery}${attrsQuery}${inheritQuery}${externalQuery}` | ||
let customRequest | ||
if (enableInlineMatchResource) { | ||
customRequest = stringifyRequest( | ||
genMatchResource(loaderContext, src, query, block.attrs.lang) | ||
) | ||
} else { | ||
customRequest = stringifyRequest(src + query) | ||
} | ||
return ( | ||
`import block${i} from ${stringifyRequest(src + query)}\n` + | ||
`import block${i} from ${customRequest}\n` + | ||
`if (typeof block${i} === 'function') block${i}(component)` | ||
@@ -27,0 +40,0 @@ ) |
@@ -1,2 +0,2 @@ | ||
const { attrsToQuery } = require('./utils') | ||
const { attrsToQuery, genMatchResource } = require('./utils') | ||
const hotReloadAPIPath = JSON.stringify(require.resolve('vue-hot-reload-api')) | ||
@@ -13,3 +13,4 @@ const nonWhitespaceRE = /\S+/ | ||
needsExplicitInjection, | ||
isProduction | ||
isProduction, | ||
enableInlineMatchResource | ||
) { | ||
@@ -26,3 +27,6 @@ let styleImportsCode = `` | ||
const attrsQuery = attrsToQuery(style.attrs, 'css') | ||
const inheritQuery = `&${loaderContext.resourceQuery.slice(1)}` | ||
const lang = String(style.attrs.lang || 'css') | ||
const inheritQuery = loaderContext.resourceQuery.slice(1) | ||
? `&${loaderContext.resourceQuery.slice(1)}` | ||
: '' | ||
// make sure to only pass id not src importing so that we don't inject | ||
@@ -32,4 +36,11 @@ // duplicate tags when multiple components import the same css file | ||
const prodQuery = isProduction ? `&prod` : `` | ||
const query = `?vue&type=style&index=${i}${idQuery}${prodQuery}${attrsQuery}${inheritQuery}` | ||
return stringifyRequest(src + query) | ||
const externalQuery = style.src ? `&external` : `` | ||
const query = `?vue&type=style&index=${i}${idQuery}${prodQuery}${attrsQuery}${inheritQuery}${externalQuery}` | ||
let styleRequest | ||
if (enableInlineMatchResource) { | ||
styleRequest = stringifyRequest(genMatchResource(loaderContext, src, query, lang)) | ||
} else { | ||
styleRequest = stringifyRequest(src + query) | ||
} | ||
return styleRequest | ||
} | ||
@@ -36,0 +47,0 @@ |
@@ -21,1 +21,29 @@ const qs = require('querystring') | ||
} | ||
exports.genMatchResource = (context, resourcePath, resourceQuery, lang) => { | ||
resourceQuery = resourceQuery || '' | ||
const loaders = [] | ||
const parsedQuery = qs.parse(resourceQuery.slice(1)) | ||
// process non-external resources | ||
if ('vue' in parsedQuery && !('external' in parsedQuery)) { | ||
const currentRequest = context.loaders | ||
.slice(context.loaderIndex) | ||
.map((obj) => obj.request) | ||
loaders.push(...currentRequest) | ||
} | ||
const loaderString = loaders.join('!') | ||
return `${resourcePath}${lang ? `.${lang}` : ''}${resourceQuery}!=!${ | ||
loaderString ? `${loaderString}!` : '' | ||
}${resourcePath}${resourceQuery}` | ||
} | ||
exports.testWebpack5 = (compiler) => { | ||
if (!compiler) { | ||
return false | ||
} | ||
const webpackVersion = compiler.webpack && compiler.webpack.version | ||
return Boolean(webpackVersion && Number(webpackVersion.split('.')[0]) > 4) | ||
} |
@@ -21,2 +21,3 @@ import { Plugin } from 'webpack' | ||
exposeFilename?: boolean | ||
experimentalInlineMatchResource?: boolean | ||
} | ||
@@ -23,0 +24,0 @@ } |
@@ -7,3 +7,7 @@ const path = require('path') | ||
const loaderUtils = require('loader-utils') | ||
const { attrsToQuery } = require('./codegen/utils') | ||
const { | ||
attrsToQuery, | ||
testWebpack5, | ||
genMatchResource | ||
} = require('./codegen/utils') | ||
const genStylesCode = require('./codegen/styleInjection') | ||
@@ -42,10 +46,12 @@ const { genHotReloadCode } = require('./codegen/hotReload') | ||
resourcePath, | ||
resourceQuery = '' | ||
resourceQuery: _resourceQuery = '', | ||
_compiler | ||
} = loaderContext | ||
const rawQuery = resourceQuery.slice(1) | ||
const inheritQuery = `&${rawQuery}` | ||
const isWebpack5 = testWebpack5(_compiler) | ||
const rawQuery = _resourceQuery.slice(1) | ||
const resourceQuery = rawQuery ? `&${rawQuery}` : '' | ||
const incomingQuery = qs.parse(rawQuery) | ||
const options = loaderUtils.getOptions(loaderContext) || {} | ||
const enableInlineMatchResource = | ||
isWebpack5 && Boolean(options.experimentalInlineMatchResource) | ||
const isServer = target === 'node' | ||
@@ -116,10 +122,20 @@ const isShadow = !!options.shadowMode | ||
if (script || scriptSetup) { | ||
// const lang = script?.lang || scriptSetup?.lang | ||
const lang = script.lang || (scriptSetup && scriptSetup.lang) | ||
// isTS = !!(lang && /tsx?/.test(lang)) | ||
const externalQuery = | ||
script && !scriptSetup && script.src ? `&external` : `` | ||
const src = (script && !scriptSetup && script.src) || resourcePath | ||
const attrsQuery = attrsToQuery((scriptSetup || script).attrs, 'js') | ||
const query = `?vue&type=script${attrsQuery}${inheritQuery}` | ||
const request = stringifyRequest(src + query) | ||
const query = `?vue&type=script${attrsQuery}${resourceQuery}${externalQuery}` | ||
let scriptRequest | ||
if (enableInlineMatchResource) { | ||
scriptRequest = stringifyRequest( | ||
genMatchResource(loaderContext, src, query, lang || 'js') | ||
) | ||
} else { | ||
scriptRequest = stringifyRequest(src + query) | ||
} | ||
scriptImport = | ||
`import script from ${request}\n` + `export * from ${request}` // support named exports | ||
`import script from ${scriptRequest}\n` + `export * from ${scriptRequest}` // support named exports | ||
} | ||
@@ -132,2 +148,3 @@ | ||
const src = descriptor.template.src || resourcePath | ||
const externalQuery = descriptor.template.src ? `&external` : `` | ||
const idQuery = `&id=${id}` | ||
@@ -138,5 +155,12 @@ const scopedQuery = hasScoped ? `&scoped=true` : `` | ||
// options.enableTsInTemplate !== false && isTS ? `&ts=true` : `` | ||
const query = `?vue&type=template${idQuery}${scopedQuery}${attrsQuery}${inheritQuery}` | ||
const request = (templateRequest = stringifyRequest(src + query)) | ||
templateImport = `import { render, staticRenderFns } from ${request}` | ||
const query = `?vue&type=template${idQuery}${scopedQuery}${attrsQuery}${resourceQuery}${externalQuery}` | ||
if (enableInlineMatchResource) { | ||
templateRequest = stringifyRequest( | ||
// TypeScript syntax in template expressions is not supported in Vue 2, so the lang is always 'js' | ||
genMatchResource(loaderContext, src, query, 'js') | ||
) | ||
} else { | ||
templateRequest = stringifyRequest(src + query) | ||
} | ||
templateImport = `import { render, staticRenderFns } from ${templateRequest}` | ||
} | ||
@@ -155,3 +179,4 @@ | ||
isServer || isShadow, // needs explicit injection? | ||
isProduction | ||
isProduction, | ||
enableInlineMatchResource | ||
) | ||
@@ -182,6 +207,8 @@ } | ||
code += genCustomBlocksCode( | ||
loaderContext, | ||
descriptor.customBlocks, | ||
resourcePath, | ||
resourceQuery, | ||
stringifyRequest | ||
stringifyRequest, | ||
enableInlineMatchResource | ||
) | ||
@@ -188,0 +215,0 @@ } |
@@ -8,2 +8,3 @@ const qs = require('querystring') | ||
const { resolveCompiler } = require('../compiler') | ||
const { testWebpack5 } = require('../codegen/utils') | ||
@@ -57,2 +58,3 @@ const isESLintLoader = (l) => /(\/|\\|@)eslint-loader/.test(l.path) | ||
const query = qs.parse(this.resourceQuery.slice(1)) | ||
const isWebpack5 = testWebpack5(this._compiler) | ||
@@ -83,3 +85,3 @@ let loaders = this.loaders | ||
const genRequest = (loaders) => { | ||
const genRequest = (loaders, lang) => { | ||
// Important: dedupe since both the original rule | ||
@@ -95,2 +97,4 @@ // and the cloned rule would match a source import request. | ||
const loaderStrings = [] | ||
const enableInlineMatchResource = | ||
isWebpack5 && options.experimentalInlineMatchResource | ||
@@ -108,2 +112,10 @@ loaders.forEach((loader) => { | ||
}) | ||
if (enableInlineMatchResource) { | ||
return loaderUtils.stringifyRequest( | ||
this, | ||
`${this.resourcePath}${lang ? `.${lang}` : ''}${ | ||
this.resourceQuery | ||
}!=!-!${[...loaderStrings, this.resourcePath + this.resourceQuery].join('!')}` | ||
) | ||
} | ||
@@ -119,2 +131,39 @@ return loaderUtils.stringifyRequest( | ||
if (query.type === `style`) { | ||
if (isWebpack5 && this._compiler.options.experiments && this._compiler.options.experiments.css) { | ||
// If user enables `experiments.css`, then we are trying to emit css code directly. | ||
// Although we can target requests like `xxx.vue?type=style` to match `type: "css"`, | ||
// it will make the plugin a mess. | ||
if (!options.experimentalInlineMatchResource) { | ||
this.emitError( | ||
new Error( | ||
'`experimentalInlineMatchResource` should be enabled if `experiments.css` enabled currently' | ||
) | ||
) | ||
return '' | ||
} | ||
if (query.inline || query.module) { | ||
this.emitError( | ||
new Error( | ||
'`inline` or `module` is currently not supported with `experiments.css` enabled' | ||
) | ||
) | ||
return '' | ||
} | ||
const loaderString = [stylePostLoaderPath, ...loaders] | ||
.map((loader) => { | ||
return typeof loader === 'string' ? loader : loader.request | ||
}) | ||
.join('!') | ||
const styleRequest = loaderUtils.stringifyRequest( | ||
this, | ||
`${this.resourcePath}${query.lang ? `.${query.lang}` : ''}${ | ||
this.resourceQuery | ||
}!=!-!${loaderString}!${this.resourcePath + this.resourceQuery}` | ||
) | ||
return `@import ${styleRequest};` | ||
} | ||
const cssLoaderIndex = loaders.findIndex(isCSSLoader) | ||
@@ -124,7 +173,6 @@ if (cssLoaderIndex > -1) { | ||
const beforeLoaders = loaders.slice(cssLoaderIndex + 1) | ||
const request = genRequest([ | ||
...afterLoaders, | ||
stylePostLoaderPath, | ||
...beforeLoaders | ||
]) | ||
const request = genRequest( | ||
[...afterLoaders, stylePostLoaderPath, ...beforeLoaders], | ||
query.lang || 'css' | ||
) | ||
// console.log(request) | ||
@@ -131,0 +179,0 @@ return query.module |
@@ -112,2 +112,4 @@ const { resolveCompiler } = require('./compiler') | ||
vueLoaderUse.options = vueLoaderUse.options || {} | ||
const enableInlineMatchResource = | ||
vueLoaderUse.options.experimentalInlineMatchResource | ||
@@ -169,16 +171,48 @@ // for each user rule (expect the vue rule), create a cloned rule | ||
}, | ||
options: { | ||
cacheDirectory: vueLoaderUse.options.cacheDirectory, | ||
cacheIdentifier: vueLoaderUse.options.cacheIdentifier | ||
} | ||
options: vueLoaderUse.options | ||
} | ||
// replace original rules | ||
if (enableInlineMatchResource) { | ||
// Match rules using `vue-loader` | ||
const vueLoaderRules = rules.filter((rule) => { | ||
const matchOnce = (use) => { | ||
let loaderString = '' | ||
// replace original rules | ||
compiler.options.module.rules = [ | ||
pitcher, | ||
...jsRulesForRenderFn, | ||
...(is27 ? [templateCompilerRule] : []), | ||
...clonedRules, | ||
...rules | ||
] | ||
if (!use) { | ||
return loaderString | ||
} | ||
if (typeof use === 'string') { | ||
loaderString = use | ||
} else if (Array.isArray(use)) { | ||
loaderString = matchOnce(use[0]) | ||
} else if (typeof use === 'object' && use.loader) { | ||
loaderString = use.loader | ||
} | ||
return loaderString | ||
} | ||
const loader = rule.loader || matchOnce(rule.use) | ||
return ( | ||
loader === require('../package.json').name || | ||
loader.startsWith(require.resolve('./index')) | ||
) | ||
}) | ||
compiler.options.module.rules = [ | ||
pitcher, | ||
...rules.filter((rule) => !vueLoaderRules.includes(rule)), | ||
...(is27 ? [templateCompilerRule] : []), | ||
...clonedRules, | ||
...vueLoaderRules | ||
] | ||
} else { | ||
compiler.options.module.rules = [ | ||
pitcher, | ||
...jsRulesForRenderFn, | ||
...(is27 ? [templateCompilerRule] : []), | ||
...clonedRules, | ||
...rules | ||
] | ||
} | ||
} | ||
@@ -185,0 +219,0 @@ } |
@@ -1,12 +0,17 @@ | ||
const webpack = require('webpack') | ||
let VueLoaderPlugin = null | ||
if (webpack.version && webpack.version[0] > 4) { | ||
// webpack5 and upper | ||
VueLoaderPlugin = require('./plugin-webpack5') | ||
} else { | ||
// webpack4 and lower | ||
VueLoaderPlugin = require('./plugin-webpack4') | ||
const { testWebpack5 } = require('./codegen/utils') | ||
const NS = 'vue-loader' | ||
class VueLoaderPlugin { | ||
apply(compiler) { | ||
let Ctor = null | ||
if (testWebpack5(compiler)) { | ||
// webpack5 and upper | ||
Ctor = require('./plugin-webpack5') | ||
} else { | ||
// webpack4 and lower | ||
Ctor = require('./plugin-webpack4') | ||
} | ||
new Ctor().apply(compiler) | ||
} | ||
} | ||
VueLoaderPlugin.NS = NS | ||
module.exports = VueLoaderPlugin |
{ | ||
"name": "vue-loader", | ||
"version": "15.10.2", | ||
"version": "15.11.0", | ||
"description": "Vue single-file component loader for Webpack", | ||
@@ -59,2 +59,3 @@ "main": "lib/index.js", | ||
"conventional-changelog-cli": "^1.3.22", | ||
"cross-env": "^7.0.3", | ||
"css-loader": "^1.0.0", | ||
@@ -98,4 +99,6 @@ "eslint": "^4.19.0", | ||
}, | ||
"packageManager": "pnpm@8.9.2", | ||
"scripts": { | ||
"test": "jest --env node", | ||
"test:match-resource": "cross-env INLINE_MATCH_RESOURCE=true jest --env node", | ||
"lint": "eslint lib test --fix", | ||
@@ -102,0 +105,0 @@ "build": "webpack --config example/webpack.config.js --hide-modules", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
90729
1588
44