first commit

This commit is contained in:
monjack
2025-06-20 18:01:48 +08:00
commit 6daa6d65c1
24611 changed files with 2512443 additions and 0 deletions

View File

@ -0,0 +1,7 @@
const path = require('path')
module.exports = function getAssetPath (options, filePath) {
return options.assetsDir
? path.posix.join(options.assetsDir, filePath)
: filePath
}

View File

@ -0,0 +1,3 @@
module.exports = function getBaseUrl (options) {
return options.publicPath === 'auto' ? '' : options.publicPath
}

View File

@ -0,0 +1,9 @@
module.exports = function getPadLength (obj) {
let longest = 10
for (const name in obj) {
if (name.length + 1 > longest) {
longest = name.length + 1
}
}
return longest
}

View File

@ -0,0 +1,13 @@
const { semver, loadModule } = require('@vue/cli-shared-utils')
/**
* Get the major Vue version that the user project uses
* @param {string} cwd the user project root
* @returns {2|3}
*/
module.exports = function getVueMajor (cwd) {
const vue = loadModule('vue', cwd)
// TODO: make Vue 3 the default version
const vueMajor = vue ? semver.major(vue.version) : 2
return vueMajor
}

View File

@ -0,0 +1,4 @@
module.exports = function isAbsoluteUrl (url) {
// A URL is considered absolute if it begins with "<scheme>://" or "//"
return /^([a-z][a-z\d+\-.]*:)?\/\//i.test(url)
}

View File

@ -0,0 +1,38 @@
const fs = require('fs')
const path = require('path')
const { pathToFileURL } = require('url')
const isFileEsm = require('is-file-esm')
const { loadModule } = require('@vue/cli-shared-utils')
module.exports = function loadFileConfig (context) {
let fileConfig, fileConfigPath
const possibleConfigPaths = [
process.env.VUE_CLI_SERVICE_CONFIG_PATH,
'./vue.config.js',
'./vue.config.cjs',
'./vue.config.mjs'
]
for (const p of possibleConfigPaths) {
const resolvedPath = p && path.resolve(context, p)
if (resolvedPath && fs.existsSync(resolvedPath)) {
fileConfigPath = resolvedPath
break
}
}
if (fileConfigPath) {
const { esm } = isFileEsm.sync(fileConfigPath)
if (esm) {
fileConfig = import(pathToFileURL(fileConfigPath))
} else {
fileConfig = loadModule(fileConfigPath, context)
}
}
return {
fileConfig,
fileConfigPath
}
}

View File

@ -0,0 +1,205 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file at
* https://github.com/facebookincubator/create-react-app/blob/master/LICENSE
*/
const fs = require('fs')
const url = require('url')
const path = require('path')
const { chalk } = require('@vue/cli-shared-utils')
const address = require('address')
const defaultConfig = {
logLevel: 'silent',
secure: false,
changeOrigin: true,
ws: true,
xfwd: true
}
module.exports = function prepareProxy (proxy, appPublicFolder) {
// `proxy` lets you specify alternate servers for specific requests.
// It can either be a string or an object conforming to the Webpack dev server proxy configuration
// https://webpack.github.io/docs/webpack-dev-server.html
if (!proxy) {
return undefined
}
if (Array.isArray(proxy) || (typeof proxy !== 'object' && typeof proxy !== 'string')) {
console.log(
chalk.red(
'When specified, "proxy" in package.json must be a string or an object.'
)
)
console.log(
chalk.red('Instead, the type of "proxy" was "' + typeof proxy + '".')
)
console.log(
chalk.red(
'Either remove "proxy" from package.json, or make it an object.'
)
)
process.exit(1)
}
// If proxy is specified, let it handle any request except for
// files in the public folder and requests to the WebpackDevServer socket endpoint.
// https://github.com/facebook/create-react-app/issues/6720
function mayProxy (pathname) {
const maybePublicPath = path.resolve(appPublicFolder, pathname.slice(1))
const isPublicFileRequest = fs.existsSync(maybePublicPath) && fs.statSync(maybePublicPath).isFile()
const isWdsEndpointRequest = pathname.startsWith('/sockjs-node') // used by webpackHotDevClient
return !(isPublicFileRequest || isWdsEndpointRequest)
}
function createProxyEntry (target, usersOnProxyReq, context) {
// #2478
// There're a little-known use case that the `target` field is an object rather than a string
// https://github.com/chimurai/http-proxy-middleware/blob/master/recipes/https.md
if (typeof target === 'string' && process.platform === 'win32') {
target = resolveLoopback(target)
}
return {
target,
context (pathname, req) {
// is a static asset
if (!mayProxy(pathname)) {
return false
}
if (context) {
// Explicit context, e.g. /api
return pathname.match(context)
} else {
// not a static request
if (req.method !== 'GET') {
return true
}
// Heuristics: if request `accept`s text/html, we pick /index.html.
// Modern browsers include text/html into `accept` header when navigating.
// However API calls like `fetch()` wont generally accept text/html.
// If this heuristic doesnt work well for you, use a custom `proxy` object.
return (
req.headers.accept &&
req.headers.accept.indexOf('text/html') === -1
)
}
},
onProxyReq (proxyReq, req, res) {
if (usersOnProxyReq) {
usersOnProxyReq(proxyReq, req, res)
}
// Browsers may send Origin headers even with same-origin
// requests. To prevent CORS issues, we have to change
// the Origin to match the target URL.
if (!proxyReq.agent && proxyReq.getHeader('origin')) {
proxyReq.setHeader('origin', target)
}
},
onError: onProxyError(target)
}
}
// Support proxy as a string for those who are using the simple proxy option
if (typeof proxy === 'string') {
if (!/^http(s)?:\/\//.test(proxy)) {
console.log(
chalk.red(
'When "proxy" is specified in package.json it must start with either http:// or https://'
)
)
process.exit(1)
}
return [
Object.assign({}, defaultConfig, createProxyEntry(proxy))
]
}
// Otherwise, proxy is an object so create an array of proxies to pass to webpackDevServer
return Object.keys(proxy).map(context => {
const config = proxy[context]
if (!Object.prototype.hasOwnProperty.call(config, 'target')) {
console.log(
chalk.red(
'When `proxy` in package.json is an object, each `context` object must have a ' +
'`target` property specified as a url string'
)
)
process.exit(1)
}
const entry = createProxyEntry(config.target, config.onProxyReq, context)
return Object.assign({}, defaultConfig, config, entry)
})
}
function resolveLoopback (proxy) {
const o = new url.URL(proxy)
o.host = undefined
if (o.hostname !== 'localhost') {
return proxy
}
// Unfortunately, many languages (unlike node) do not yet support IPv6.
// This means even though localhost resolves to ::1, the application
// must fall back to IPv4 (on 127.0.0.1).
// We can re-enable this in a few years.
/* try {
o.hostname = address.ipv6() ? '::1' : '127.0.0.1';
} catch (_ignored) {
o.hostname = '127.0.0.1';
} */
try {
// Check if we're on a network; if we are, chances are we can resolve
// localhost. Otherwise, we can just be safe and assume localhost is
// IPv4 for maximum compatibility.
if (!address.ip()) {
o.hostname = '127.0.0.1'
}
} catch (_ignored) {
o.hostname = '127.0.0.1'
}
return url.format(o)
}
// We need to provide a custom onError function for httpProxyMiddleware.
// It allows us to log custom error messages on the console.
function onProxyError (proxy) {
return (err, req, res) => {
const host = req.headers && req.headers.host
console.log(
chalk.red('Proxy error:') +
' Could not proxy request ' +
chalk.cyan(req.url) +
' from ' +
chalk.cyan(host) +
' to ' +
chalk.cyan(proxy) +
'.'
)
console.log(
'See https://nodejs.org/api/errors.html#errors_common_system_errors for more information (' +
chalk.cyan(err.code) +
').'
)
console.log()
// And immediately send the proper error response to the client.
// Otherwise, the request will eventually timeout with ERR_EMPTY_RESPONSE on the client side.
if (res.writeHead && !res.headersSent) {
res.writeHead(500)
}
res.end(
'Proxy error: Could not proxy request ' +
req.url +
' from ' +
host +
' to ' +
proxy +
' (' +
err.code +
').'
)
}
}

View File

@ -0,0 +1,70 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file at
* https://github.com/facebookincubator/create-react-app/blob/master/LICENSE
*/
const url = require('url')
const { chalk } = require('@vue/cli-shared-utils')
const address = require('address')
const defaultGateway = require('default-gateway')
module.exports = function prepareUrls (protocol, host, port, pathname = '/') {
const formatUrl = hostname =>
url.format({
protocol,
hostname,
port,
pathname
})
const prettyPrintUrl = hostname =>
url.format({
protocol,
hostname,
port: chalk.bold(port),
pathname
})
const isUnspecifiedHost = host === '0.0.0.0' || host === '::'
let prettyHost, lanUrlForConfig
let lanUrlForTerminal = chalk.gray('unavailable')
if (isUnspecifiedHost) {
prettyHost = 'localhost'
try {
// This can only return an IPv4 address
const result = defaultGateway.v4.sync()
lanUrlForConfig = address.ip(result && result.interface)
if (lanUrlForConfig) {
// Check if the address is a private ip
// https://en.wikipedia.org/wiki/Private_network#Private_IPv4_address_spaces
if (
/^10[.]|^172[.](1[6-9]|2[0-9]|3[0-1])[.]|^192[.]168[.]/.test(
lanUrlForConfig
)
) {
// Address is private, format it for later use
lanUrlForTerminal = prettyPrintUrl(lanUrlForConfig)
} else {
// Address is not private, so we will discard it
lanUrlForConfig = undefined
}
}
} catch (_e) {
// ignored
}
} else {
prettyHost = host
lanUrlForConfig = host
lanUrlForTerminal = prettyPrintUrl(lanUrlForConfig)
}
const localUrlForTerminal = prettyPrintUrl(prettyHost)
const localUrlForBrowser = formatUrl(prettyHost)
return {
lanUrlForConfig,
lanUrlForTerminal,
localUrlForTerminal,
localUrlForBrowser
}
}

View File

@ -0,0 +1,23 @@
const getBaseUrl = require('./getBaseUrl')
const prefixRE = /^VUE_APP_/
module.exports = function resolveClientEnv (options, raw) {
const env = {}
Object.keys(process.env).forEach(key => {
if (prefixRE.test(key) || key === 'NODE_ENV') {
env[key] = process.env[key]
}
})
env.BASE_URL = getBaseUrl(options)
if (raw) {
return env
}
for (const key in env) {
env[key] = JSON.stringify(env[key])
}
return {
'process.env': env
}
}

View File

@ -0,0 +1,47 @@
const { chalk } = require('@vue/cli-shared-utils')
const rules = [
{
type: 'cant-resolve-loader',
re: /Can't resolve '(.*loader)'/,
msg: (e, match) => (
`Failed to resolve loader: ${chalk.yellow(match[1])}\n` +
`You may need to install it.`
)
}
]
exports.transformer = error => {
if (error.webpackError) {
const message = typeof error.webpackError === 'string'
? error.webpackError
: error.webpackError.message || ''
for (const { re, msg, type } of rules) {
const match = message.match(re)
if (match) {
return Object.assign({}, error, {
// type is necessary to avoid being printed as default error
// by friendly-error-webpack-plugin
type,
shortMessage: msg(error, match)
})
}
}
// no match, unknown webpack error without a message.
// friendly-error-webpack-plugin fails to handle this.
if (!error.message) {
return Object.assign({}, error, {
type: 'unknown-webpack-error',
shortMessage: message
})
}
}
return error
}
exports.formatter = errors => {
errors = errors.filter(e => e.shortMessage)
if (errors.length) {
return errors.map(e => e.shortMessage)
}
}

View File

@ -0,0 +1,5 @@
const path = require('path')
module.exports = function resolveLocal (...args) {
return path.join(__dirname, '../../', ...args)
}

View File

@ -0,0 +1,83 @@
const path = require('path')
const { chalk, warn, error } = require('@vue/cli-shared-utils')
const { validate } = require('../options')
function ensureSlash (config, key) {
const val = config[key]
if (typeof val === 'string') {
config[key] = val.replace(/([^/])$/, '$1/')
}
}
function removeSlash (config, key) {
if (typeof config[key] === 'string') {
config[key] = config[key].replace(/\/$/g, '')
}
}
module.exports = function resolveUserConfig ({
inlineOptions,
pkgConfig,
fileConfig,
fileConfigPath
}) {
if (fileConfig) {
if (typeof fileConfig === 'function') {
fileConfig = fileConfig()
}
if (!fileConfig || typeof fileConfig !== 'object') {
throw new Error(
`Error loading ${chalk.bold(fileConfigPath)}: ` +
`should export an object or a function that returns object.`
)
}
}
// package.vue
if (pkgConfig && typeof pkgConfig !== 'object') {
throw new Error(
`Error loading Vue CLI config in ${chalk.bold(`package.json`)}: ` +
`the "vue" field should be an object.`
)
}
let resolved, resolvedFrom
if (fileConfig) {
const configFileName = path.basename(fileConfigPath)
if (pkgConfig) {
warn(
`"vue" field in package.json ignored ` +
`due to presence of ${chalk.bold(configFileName)}.`
)
warn(
`You should migrate it into ${chalk.bold(configFileName)} ` +
`and remove it from package.json.`
)
}
resolved = fileConfig
resolvedFrom = configFileName
} else if (pkgConfig) {
resolved = pkgConfig
resolvedFrom = '"vue" field in package.json'
} else {
resolved = inlineOptions || {}
resolvedFrom = 'inline options'
}
// normalize some options
if (resolved.publicPath !== 'auto') {
ensureSlash(resolved, 'publicPath')
}
if (typeof resolved.publicPath === 'string') {
resolved.publicPath = resolved.publicPath.replace(/^\.\//, '')
}
removeSlash(resolved, 'outputDir')
// validate options
validate(resolved, msg => {
error(`Invalid options in ${chalk.bold(resolvedFrom)}: ${msg}`)
})
return resolved
}

View File

@ -0,0 +1,70 @@
// copied from @vue/babel-preset-app
const { semver } = require('@vue/cli-shared-utils')
const { default: getTargets } = require('@babel/helper-compilation-targets')
// See the result at <https://github.com/babel/babel/blob/v7.13.15/packages/babel-compat-data/data/native-modules.json>
const allModuleTargets = getTargets(
{ esmodules: true },
{ ignoreBrowserslistConfig: true }
)
function getIntersectionTargets (targets, constraintTargets) {
const intersection = Object.keys(constraintTargets).reduce(
(results, browser) => {
// exclude the browsers that the user does not need
if (!targets[browser]) {
return results
}
// if the user-specified version is higher the minimum version that supports esmodule, than use it
results[browser] = semver.gt(
semver.coerce(constraintTargets[browser]),
semver.coerce(targets[browser])
)
? constraintTargets[browser]
: targets[browser]
return results
},
{}
)
return intersection
}
function getModuleTargets (targets) {
// use the intersection of modern mode browsers and user defined targets config
return getIntersectionTargets(targets, allModuleTargets)
}
function doAllTargetsSupportModule (targets) {
const browserList = Object.keys(targets)
return browserList.every(browserName => {
if (!allModuleTargets[browserName]) {
return false
}
return semver.gte(
semver.coerce(targets[browserName]),
semver.coerce(allModuleTargets[browserName])
)
})
}
// get browserslist targets in current working directory
const projectTargets = getTargets()
const projectModuleTargets = getModuleTargets(projectTargets)
const allProjectTargetsSupportModule = doAllTargetsSupportModule(projectTargets)
module.exports = {
getTargets,
getModuleTargets,
getIntersectionTargets,
doAllTargetsSupportModule,
projectTargets,
projectModuleTargets,
allProjectTargetsSupportModule
}

View File

@ -0,0 +1,38 @@
module.exports = function validateWebpackConfig (
webpackConfig,
api,
options,
target = 'app'
) {
const singleConfig = Array.isArray(webpackConfig)
? webpackConfig[0]
: webpackConfig
const actualTargetDir = singleConfig.output.path
if (actualTargetDir !== api.resolve(options.outputDir)) {
// user directly modifies output.path in configureWebpack or chainWebpack.
// this is not supported because there's no way for us to give copy
// plugin the correct value this way.
throw new Error(
`\n\nConfiguration Error: ` +
`Avoid modifying webpack output.path directly. ` +
`Use the "outputDir" option instead.\n`
)
}
if (actualTargetDir === api.service.context) {
throw new Error(
`\n\nConfiguration Error: ` +
`Do not set output directory to project root.\n`
)
}
if (target === 'app' && singleConfig.output.publicPath !== options.publicPath) {
throw new Error(
`\n\nConfiguration Error: ` +
`Avoid modifying webpack output.publicPath directly. ` +
`Use the "publicPath" option instead.\n`
)
}
}