From 087bc446a25f5ef26bcaff4c8b674482ac4a4def Mon Sep 17 00:00:00 2001 From: fxy060608 Date: Tue, 27 Jul 2021 22:41:09 +0800 Subject: [PATCH] wip(app): nvue --- package.json | 3 +- .../uni-cli-nvue/dist/webpack/config/index.js | 4 + .../dist/webpack/config/module/index.js | 7 + .../dist/webpack/config/module/rules/index.js | 9 + .../dist/webpack/config/plugins/index.js | 8 +- .../dist/webpack/config/plugins/vueLoader.js | 5 + .../lib/vue-loader/dist/cssModules.d.ts | 1 + .../lib/vue-loader/dist/cssModules.js | 21 ++ .../lib/vue-loader/dist/descriptorCache.d.ts | 3 + .../lib/vue-loader/dist/descriptorCache.js | 33 +++ .../lib/vue-loader/dist/formatError.d.ts | 2 + .../lib/vue-loader/dist/formatError.js | 16 ++ .../lib/vue-loader/dist/hotReload.d.ts | 1 + .../lib/vue-loader/dist/hotReload.js | 26 +++ .../lib/vue-loader/dist/index.d.ts | 17 ++ .../uni-cli-nvue/lib/vue-loader/dist/index.js | 221 ++++++++++++++++++ .../lib/vue-loader/dist/pitcher.d.ts | 4 + .../lib/vue-loader/dist/pitcher.js | 100 ++++++++ .../lib/vue-loader/dist/plugin.d.ts | 7 + .../lib/vue-loader/dist/plugin.js | 13 ++ .../lib/vue-loader/dist/pluginWebpack4.d.ts | 6 + .../lib/vue-loader/dist/pluginWebpack4.js | 160 +++++++++++++ .../lib/vue-loader/dist/pluginWebpack5.d.ts | 6 + .../lib/vue-loader/dist/pluginWebpack5.js | 205 ++++++++++++++++ .../lib/vue-loader/dist/resolveScript.d.ts | 11 + .../lib/vue-loader/dist/resolveScript.js | 70 ++++++ .../lib/vue-loader/dist/select.d.ts | 6 + .../lib/vue-loader/dist/select.js | 41 ++++ .../vue-loader/dist/styleInlineLoader.d.ts | 3 + .../lib/vue-loader/dist/styleInlineLoader.js | 7 + .../lib/vue-loader/dist/stylePostLoader.d.ts | 3 + .../lib/vue-loader/dist/stylePostLoader.js | 26 +++ .../lib/vue-loader/dist/templateLoader.d.ts | 3 + .../lib/vue-loader/dist/templateLoader.js | 69 ++++++ .../uni-cli-nvue/lib/vue-loader/package.json | 95 ++++++++ packages/uni-cli-nvue/package.json | 1 + .../uni-cli-nvue/src/webpack/config/index.ts | 4 + .../src/webpack/config/module/index.ts | 7 + .../src/webpack/config/module/rules/index.ts | 7 + .../src/webpack/config/plugins/index.ts | 9 +- .../src/webpack/config/plugins/vueLoader.ts | 2 + yarn.lock | 18 ++ 42 files changed, 1257 insertions(+), 3 deletions(-) create mode 100644 packages/uni-cli-nvue/dist/webpack/config/module/index.js create mode 100644 packages/uni-cli-nvue/dist/webpack/config/module/rules/index.js create mode 100644 packages/uni-cli-nvue/dist/webpack/config/plugins/vueLoader.js create mode 100644 packages/uni-cli-nvue/lib/vue-loader/dist/cssModules.d.ts create mode 100644 packages/uni-cli-nvue/lib/vue-loader/dist/cssModules.js create mode 100644 packages/uni-cli-nvue/lib/vue-loader/dist/descriptorCache.d.ts create mode 100644 packages/uni-cli-nvue/lib/vue-loader/dist/descriptorCache.js create mode 100644 packages/uni-cli-nvue/lib/vue-loader/dist/formatError.d.ts create mode 100644 packages/uni-cli-nvue/lib/vue-loader/dist/formatError.js create mode 100644 packages/uni-cli-nvue/lib/vue-loader/dist/hotReload.d.ts create mode 100644 packages/uni-cli-nvue/lib/vue-loader/dist/hotReload.js create mode 100644 packages/uni-cli-nvue/lib/vue-loader/dist/index.d.ts create mode 100644 packages/uni-cli-nvue/lib/vue-loader/dist/index.js create mode 100644 packages/uni-cli-nvue/lib/vue-loader/dist/pitcher.d.ts create mode 100644 packages/uni-cli-nvue/lib/vue-loader/dist/pitcher.js create mode 100644 packages/uni-cli-nvue/lib/vue-loader/dist/plugin.d.ts create mode 100644 packages/uni-cli-nvue/lib/vue-loader/dist/plugin.js create mode 100644 packages/uni-cli-nvue/lib/vue-loader/dist/pluginWebpack4.d.ts create mode 100644 packages/uni-cli-nvue/lib/vue-loader/dist/pluginWebpack4.js create mode 100644 packages/uni-cli-nvue/lib/vue-loader/dist/pluginWebpack5.d.ts create mode 100644 packages/uni-cli-nvue/lib/vue-loader/dist/pluginWebpack5.js create mode 100644 packages/uni-cli-nvue/lib/vue-loader/dist/resolveScript.d.ts create mode 100644 packages/uni-cli-nvue/lib/vue-loader/dist/resolveScript.js create mode 100644 packages/uni-cli-nvue/lib/vue-loader/dist/select.d.ts create mode 100644 packages/uni-cli-nvue/lib/vue-loader/dist/select.js create mode 100644 packages/uni-cli-nvue/lib/vue-loader/dist/styleInlineLoader.d.ts create mode 100644 packages/uni-cli-nvue/lib/vue-loader/dist/styleInlineLoader.js create mode 100644 packages/uni-cli-nvue/lib/vue-loader/dist/stylePostLoader.d.ts create mode 100644 packages/uni-cli-nvue/lib/vue-loader/dist/stylePostLoader.js create mode 100644 packages/uni-cli-nvue/lib/vue-loader/dist/templateLoader.d.ts create mode 100644 packages/uni-cli-nvue/lib/vue-loader/dist/templateLoader.js create mode 100644 packages/uni-cli-nvue/lib/vue-loader/package.json create mode 100644 packages/uni-cli-nvue/src/webpack/config/module/index.ts create mode 100644 packages/uni-cli-nvue/src/webpack/config/module/rules/index.ts create mode 100644 packages/uni-cli-nvue/src/webpack/config/plugins/vueLoader.ts diff --git a/package.json b/package.json index 699341d4e..da989122e 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,8 @@ "scripts": { "build": "node scripts/build.js", "build:h5": "node scripts/build.js uni-app uni-cli-shared uni-h5 uni-i18n uni-shared uni-h5-vite vite-plugin-uni", - "build:app": "node scripts/build.js uni-app-plus uni-app-vite uni-app-vue", + "build:app": "node scripts/build.js uni-app-plus uni-app-vite uni-app-vue uni-cli-nvue", + "build:mp": "node scripts/build.js uni-mp-alipay uni-mp-baidu uni-mp-qq uni-mp-toutiao uni-mp-weixin uni-quickapp-webview", "size": "npm run build size-check", "lint": "eslint packages/*/src/**/*.ts", "format": "prettier --write --parser typescript \"packages/**/*.ts?(x)\"", diff --git a/packages/uni-cli-nvue/dist/webpack/config/index.js b/packages/uni-cli-nvue/dist/webpack/config/index.js index 8c4569951..e7febf655 100644 --- a/packages/uni-cli-nvue/dist/webpack/config/index.js +++ b/packages/uni-cli-nvue/dist/webpack/config/index.js @@ -3,6 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.createConfig = void 0; const optimization_1 = require("./optimization"); const output_1 = require("./output"); +const module_1 = require("./module"); +const plugins_1 = require("./plugins"); function createConfig(mode) { return { target: 'node', @@ -17,6 +19,8 @@ function createConfig(mode) { }, optimization: optimization_1.optimization, output: output_1.output, + module: module_1.module, + plugins: plugins_1.plugins, }; } exports.createConfig = createConfig; diff --git a/packages/uni-cli-nvue/dist/webpack/config/module/index.js b/packages/uni-cli-nvue/dist/webpack/config/module/index.js new file mode 100644 index 000000000..5a803fbd8 --- /dev/null +++ b/packages/uni-cli-nvue/dist/webpack/config/module/index.js @@ -0,0 +1,7 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.module = void 0; +const rules_1 = require("./rules"); +exports.module = { + rules: rules_1.rules, +}; diff --git a/packages/uni-cli-nvue/dist/webpack/config/module/rules/index.js b/packages/uni-cli-nvue/dist/webpack/config/module/rules/index.js new file mode 100644 index 000000000..775d91e22 --- /dev/null +++ b/packages/uni-cli-nvue/dist/webpack/config/module/rules/index.js @@ -0,0 +1,9 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.rules = void 0; +exports.rules = [ + { + test: [/\.nvue(\?[^?]+)?$/, /\.vue(\?[^?]+)?$/], + loader: 'vue-loader', + }, +]; diff --git a/packages/uni-cli-nvue/dist/webpack/config/plugins/index.js b/packages/uni-cli-nvue/dist/webpack/config/plugins/index.js index ca2fac762..40d1b003c 100644 --- a/packages/uni-cli-nvue/dist/webpack/config/plugins/index.js +++ b/packages/uni-cli-nvue/dist/webpack/config/plugins/index.js @@ -4,4 +4,10 @@ exports.plugins = void 0; const define_1 = require("./define"); const banner_1 = require("./banner"); const provide_1 = require("./provide"); -exports.plugins = [define_1.define, banner_1.banner, provide_1.provide]; +const vueLoader_1 = require("./vueLoader"); +exports.plugins = [ + define_1.define, + banner_1.banner, + provide_1.provide, + vueLoader_1.vueLoaderPlugin, +]; diff --git a/packages/uni-cli-nvue/dist/webpack/config/plugins/vueLoader.js b/packages/uni-cli-nvue/dist/webpack/config/plugins/vueLoader.js new file mode 100644 index 000000000..4e60eb834 --- /dev/null +++ b/packages/uni-cli-nvue/dist/webpack/config/plugins/vueLoader.js @@ -0,0 +1,5 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.vueLoaderPlugin = void 0; +const { VueLoaderPlugin } = require('../../../../lib/vue-loader/dist'); +exports.vueLoaderPlugin = new VueLoaderPlugin(); diff --git a/packages/uni-cli-nvue/lib/vue-loader/dist/cssModules.d.ts b/packages/uni-cli-nvue/lib/vue-loader/dist/cssModules.d.ts new file mode 100644 index 000000000..8f28ca7ae --- /dev/null +++ b/packages/uni-cli-nvue/lib/vue-loader/dist/cssModules.d.ts @@ -0,0 +1 @@ +export declare function genCSSModulesCode(id: string, index: number, request: string, moduleName: string | boolean, needsHotReload: boolean): string; diff --git a/packages/uni-cli-nvue/lib/vue-loader/dist/cssModules.js b/packages/uni-cli-nvue/lib/vue-loader/dist/cssModules.js new file mode 100644 index 000000000..23497017c --- /dev/null +++ b/packages/uni-cli-nvue/lib/vue-loader/dist/cssModules.js @@ -0,0 +1,21 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.genCSSModulesCode = void 0; +function genCSSModulesCode(id, index, request, moduleName, needsHotReload) { + const styleVar = `style${index}`; + let code = `\nimport ${styleVar} from ${request}`; + // inject variable + const name = typeof moduleName === 'string' ? moduleName : '$style'; + code += `\ncssModules["${name}"] = ${styleVar}`; + if (needsHotReload) { + code += ` +if (module.hot) { + module.hot.accept(${request}, () => { + cssModules["${name}"] = ${styleVar} + __VUE_HMR_RUNTIME__.rerender("${id}") + }) +}`; + } + return code; +} +exports.genCSSModulesCode = genCSSModulesCode; diff --git a/packages/uni-cli-nvue/lib/vue-loader/dist/descriptorCache.d.ts b/packages/uni-cli-nvue/lib/vue-loader/dist/descriptorCache.d.ts new file mode 100644 index 000000000..09e3a767f --- /dev/null +++ b/packages/uni-cli-nvue/lib/vue-loader/dist/descriptorCache.d.ts @@ -0,0 +1,3 @@ +import { SFCDescriptor } from '@vue/compiler-sfc'; +export declare function setDescriptor(filename: string, entry: SFCDescriptor): void; +export declare function getDescriptor(filename: string): SFCDescriptor; diff --git a/packages/uni-cli-nvue/lib/vue-loader/dist/descriptorCache.js b/packages/uni-cli-nvue/lib/vue-loader/dist/descriptorCache.js new file mode 100644 index 000000000..dc9d8bf6b --- /dev/null +++ b/packages/uni-cli-nvue/lib/vue-loader/dist/descriptorCache.js @@ -0,0 +1,33 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.getDescriptor = exports.setDescriptor = void 0; +const fs = require("fs"); +const compiler_sfc_1 = require("@vue/compiler-sfc"); +const cache = new Map(); +function setDescriptor(filename, entry) { + cache.set(cleanQuery(filename), entry); +} +exports.setDescriptor = setDescriptor; +function getDescriptor(filename) { + filename = cleanQuery(filename); + if (cache.has(filename)) { + return cache.get(filename); + } + // This function should only be called after the descriptor has been + // cached by the main loader. + // If this is somehow called without a cache hit, it's probably due to sub + // loaders being run in separate threads. The only way to deal with this is to + // read from disk directly... + const source = fs.readFileSync(filename, 'utf-8'); + const { descriptor } = compiler_sfc_1.parse(source, { + filename, + sourceMap: true, + }); + cache.set(filename, descriptor); + return descriptor; +} +exports.getDescriptor = getDescriptor; +function cleanQuery(str) { + const i = str.indexOf('?'); + return i > 0 ? str.slice(0, i) : str; +} diff --git a/packages/uni-cli-nvue/lib/vue-loader/dist/formatError.d.ts b/packages/uni-cli-nvue/lib/vue-loader/dist/formatError.d.ts new file mode 100644 index 000000000..e0c1c7158 --- /dev/null +++ b/packages/uni-cli-nvue/lib/vue-loader/dist/formatError.d.ts @@ -0,0 +1,2 @@ +import { CompilerError } from '@vue/compiler-sfc'; +export declare function formatError(err: SyntaxError | CompilerError, source: string, file: string): void; diff --git a/packages/uni-cli-nvue/lib/vue-loader/dist/formatError.js b/packages/uni-cli-nvue/lib/vue-loader/dist/formatError.js new file mode 100644 index 000000000..4d1eb1938 --- /dev/null +++ b/packages/uni-cli-nvue/lib/vue-loader/dist/formatError.js @@ -0,0 +1,16 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.formatError = void 0; +const compiler_sfc_1 = require("@vue/compiler-sfc"); +const chalk = require("chalk"); +function formatError(err, source, file) { + const loc = err.loc; + if (!loc) { + return; + } + const locString = `:${loc.start.line}:${loc.start.column}`; + const filePath = chalk.gray(`at ${file}${locString}`); + const codeframe = compiler_sfc_1.generateCodeFrame(source, loc.start.offset, loc.end.offset); + err.message = `\n${chalk.red(`VueCompilerError: ${err.message}`)}\n${filePath}\n${chalk.yellow(codeframe)}\n`; +} +exports.formatError = formatError; diff --git a/packages/uni-cli-nvue/lib/vue-loader/dist/hotReload.d.ts b/packages/uni-cli-nvue/lib/vue-loader/dist/hotReload.d.ts new file mode 100644 index 000000000..7431039a3 --- /dev/null +++ b/packages/uni-cli-nvue/lib/vue-loader/dist/hotReload.d.ts @@ -0,0 +1 @@ +export declare function genHotReloadCode(id: string, templateRequest: string | undefined): string; diff --git a/packages/uni-cli-nvue/lib/vue-loader/dist/hotReload.js b/packages/uni-cli-nvue/lib/vue-loader/dist/hotReload.js new file mode 100644 index 000000000..a6cdfa725 --- /dev/null +++ b/packages/uni-cli-nvue/lib/vue-loader/dist/hotReload.js @@ -0,0 +1,26 @@ +"use strict"; +// __VUE_HMR_RUNTIME__ is injected to global scope by @vue/runtime-core +Object.defineProperty(exports, "__esModule", { value: true }); +exports.genHotReloadCode = void 0; +function genHotReloadCode(id, templateRequest) { + return ` +/* hot reload */ +if (module.hot) { + script.__hmrId = "${id}" + const api = __VUE_HMR_RUNTIME__ + module.hot.accept() + if (!api.createRecord('${id}', script)) { + api.reload('${id}', script) + } + ${templateRequest ? genTemplateHotReloadCode(id, templateRequest) : ''} +} +`; +} +exports.genHotReloadCode = genHotReloadCode; +function genTemplateHotReloadCode(id, request) { + return ` + module.hot.accept(${request}, () => { + api.rerender('${id}', render) + }) +`; +} diff --git a/packages/uni-cli-nvue/lib/vue-loader/dist/index.d.ts b/packages/uni-cli-nvue/lib/vue-loader/dist/index.d.ts new file mode 100644 index 000000000..5873999dd --- /dev/null +++ b/packages/uni-cli-nvue/lib/vue-loader/dist/index.d.ts @@ -0,0 +1,17 @@ +import webpack = require('webpack'); +import { TemplateCompiler, CompilerOptions, SFCTemplateCompileOptions, SFCScriptCompileOptions } from '@vue/compiler-sfc'; +import VueLoaderPlugin from './plugin'; +export { VueLoaderPlugin }; +export interface VueLoaderOptions { + babelParserPlugins?: SFCScriptCompileOptions['babelParserPlugins']; + transformAssetUrls?: SFCTemplateCompileOptions['transformAssetUrls']; + compiler?: TemplateCompiler | string; + compilerOptions?: CompilerOptions; + refSugar?: boolean; + customElement?: boolean | RegExp; + hotReload?: boolean; + exposeFilename?: boolean; + appendExtension?: boolean; + isServerBuild?: boolean; +} +export default function loader(this: webpack.loader.LoaderContext, source: string): string | void; diff --git a/packages/uni-cli-nvue/lib/vue-loader/dist/index.js b/packages/uni-cli-nvue/lib/vue-loader/dist/index.js new file mode 100644 index 000000000..ae4ba5caf --- /dev/null +++ b/packages/uni-cli-nvue/lib/vue-loader/dist/index.js @@ -0,0 +1,221 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.VueLoaderPlugin = void 0; +try { + require.resolve('@vue/compiler-sfc'); +} +catch (e) { + throw new Error('vue-loader requires @vue/compiler-sfc to be present in the dependency ' + + 'tree.'); +} +const path = require("path"); +const qs = require("querystring"); +const loaderUtils = require("loader-utils"); +const hash = require("hash-sum"); +const compiler_sfc_1 = require("@vue/compiler-sfc"); +const select_1 = require("./select"); +const hotReload_1 = require("./hotReload"); +const cssModules_1 = require("./cssModules"); +const formatError_1 = require("./formatError"); +const plugin_1 = require("./plugin"); +exports.VueLoaderPlugin = plugin_1.default; +const resolveScript_1 = require("./resolveScript"); +const descriptorCache_1 = require("./descriptorCache"); +let errorEmitted = false; +function loader(source) { + var _a; + const loaderContext = this; + // check if plugin is installed + if (!errorEmitted && + !loaderContext['thread-loader'] && + !loaderContext[plugin_1.default.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 { mode, target, sourceMap, rootContext, resourcePath, resourceQuery = '', } = loaderContext; + const rawQuery = resourceQuery.slice(1); + const incomingQuery = qs.parse(rawQuery); + const options = (loaderUtils.getOptions(loaderContext) || + {}); + const isServer = (_a = options.isServerBuild) !== null && _a !== void 0 ? _a : target === 'node'; + const isProduction = mode === 'production' || process.env.NODE_ENV === 'production'; + const filename = resourcePath.replace(/\?.*$/, ''); + const { descriptor, errors } = compiler_sfc_1.parse(source, { + filename, + sourceMap, + }); + const asCustomElement = typeof options.customElement === 'boolean' + ? options.customElement + : (options.customElement || /\.ce\.vue$/).test(filename); + // cache descriptor + descriptorCache_1.setDescriptor(filename, descriptor); + if (errors.length) { + errors.forEach((err) => { + formatError_1.formatError(err, source, resourcePath); + loaderContext.emitError(err); + }); + return ``; + } + // module id for scoped CSS & hot-reload + const rawShortFilePath = path + .relative(rootContext || process.cwd(), filename) + .replace(/^(\.\.[\/\\])+/, ''); + const shortFilePath = rawShortFilePath.replace(/\\/g, '/'); + const id = hash(isProduction + ? shortFilePath + '\n' + source.replace(/\r\n/g, '\n') + : shortFilePath); + // 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 select_1.selectBlock(descriptor, id, options, loaderContext, incomingQuery, !!options.appendExtension); + } + // feature information + const hasScoped = descriptor.styles.some((s) => s.scoped); + const needsHotReload = !isServer && + !isProduction && + !!(descriptor.script || descriptor.scriptSetup || descriptor.template) && + options.hotReload !== false; + // script + let scriptImport = `const script = {}`; + const { script, scriptSetup } = descriptor; + if (script || scriptSetup) { + const src = (script && !scriptSetup && script.src) || resourcePath; + const attrsQuery = attrsToQuery((scriptSetup || script).attrs, 'js'); + const query = `?vue&type=script${attrsQuery}${resourceQuery}`; + const scriptRequest = stringifyRequest(src + query); + scriptImport = + `import script from ${scriptRequest}\n` + + // support named exports + `export * from ${scriptRequest}`; + } + // template + let templateImport = ``; + let templateRequest; + const renderFnName = isServer ? `ssrRender` : `render`; + const useInlineTemplate = resolveScript_1.canInlineTemplate(descriptor, isProduction); + if (descriptor.template && !useInlineTemplate) { + const src = descriptor.template.src || resourcePath; + const idQuery = `&id=${id}`; + const scopedQuery = hasScoped ? `&scoped=true` : ``; + const attrsQuery = attrsToQuery(descriptor.template.attrs); + // const bindingsQuery = script + // ? `&bindings=${JSON.stringify(script.bindings ?? {})}` + // : `` + // const varsQuery = descriptor.cssVars + // ? `&vars=${qs.escape(generateCssVars(descriptor, id, isProduction))}` + // : `` + const query = `?vue&type=template${idQuery}${scopedQuery}${attrsQuery}${resourceQuery}`; + templateRequest = stringifyRequest(src + query); + templateImport = `import { ${renderFnName} } from ${templateRequest}`; + } + // styles + let stylesCode = ``; + let hasCSSModules = false; + const nonWhitespaceRE = /\S+/; + if (descriptor.styles.length) { + descriptor.styles + .filter((style) => style.src || nonWhitespaceRE.test(style.content)) + .forEach((style, i) => { + const src = style.src || resourcePath; + const attrsQuery = attrsToQuery(style.attrs, 'css'); + // make sure to only pass id when necessary so that we don't inject + // duplicate tags when multiple components import the same css file + const idQuery = !style.src || style.scoped ? `&id=${id}` : ``; + const inlineQuery = asCustomElement ? `&inline` : ``; + const query = `?vue&type=style&index=${i}${idQuery}${inlineQuery}${attrsQuery}${resourceQuery}`; + const styleRequest = stringifyRequest(src + query); + if (style.module) { + if (asCustomElement) { + loaderContext.emitError(`