mirror of
				https://gitee.com/vant-contrib/vant.git
				synced 2025-10-27 01:32:10 +08:00 
			
		
		
		
	feat(@vant/cli): using esbuild to transform script (#10143)
* feat(@vant/cli): using esbuild to transform script * chore: update babel doc * chore: update lock * chore: update * fix: format
This commit is contained in:
		
							parent
							
								
									7b214cb87c
								
							
						
					
					
						commit
						1890cf6607
					
				| @ -1,30 +0,0 @@ | |||||||
| module.exports = function (api, options) { |  | ||||||
|   if (api) { |  | ||||||
|     api.cache.never(); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   const { BABEL_MODULE, NODE_ENV } = process.env; |  | ||||||
|   const isTest = NODE_ENV === 'test'; |  | ||||||
|   const useESModules = BABEL_MODULE !== 'commonjs' && !isTest; |  | ||||||
| 
 |  | ||||||
|   return { |  | ||||||
|     presets: [ |  | ||||||
|       [ |  | ||||||
|         require.resolve('@babel/preset-env'), |  | ||||||
|         { |  | ||||||
|           modules: useESModules ? false : 'commonjs', |  | ||||||
|           loose: options.loose, |  | ||||||
|         }, |  | ||||||
|       ], |  | ||||||
|       require.resolve('@babel/preset-typescript'), |  | ||||||
|     ], |  | ||||||
|     plugins: [ |  | ||||||
|       [ |  | ||||||
|         require.resolve('@vue/babel-plugin-jsx'), |  | ||||||
|         { |  | ||||||
|           enableObjectSlots: options.enableObjectSlots, |  | ||||||
|         }, |  | ||||||
|       ], |  | ||||||
|     ], |  | ||||||
|   }; |  | ||||||
| }; |  | ||||||
| @ -21,8 +21,6 @@ | |||||||
|     - [site.simulator.url](#sitesimulatorurl) |     - [site.simulator.url](#sitesimulatorurl) | ||||||
|     - [site.htmlMeta](#sitehtmlmeta) |     - [site.htmlMeta](#sitehtmlmeta) | ||||||
|     - [site.enableVConsole](#siteenablevconsole) |     - [site.enableVConsole](#siteenablevconsole) | ||||||
|   - [Babel](#babel) |  | ||||||
|     - [默认配置](#----) |  | ||||||
|   - [Postcss](#postcss) |   - [Postcss](#postcss) | ||||||
|     - [默认配置](#-----1) |     - [默认配置](#-----1) | ||||||
|   - [browserslist](#browserslist) |   - [browserslist](#browserslist) | ||||||
| @ -337,36 +335,13 @@ module.exports = { | |||||||
| 
 | 
 | ||||||
| 是否在 dev 时开启 [vConsole](https://github.com/Tencent/vConsole) 调试,用于移动端 debug。 | 是否在 dev 时开启 [vConsole](https://github.com/Tencent/vConsole) 调试,用于移动端 debug。 | ||||||
| 
 | 
 | ||||||
| ## Babel |  | ||||||
| 
 |  | ||||||
| 通过根目录下的`babel.config.js`文件可以对 Babel 进行配置。 |  | ||||||
| 
 |  | ||||||
| ### 默认配置 |  | ||||||
| 
 |  | ||||||
| 推荐使用`vant-cli`内置的 preset,配置如下: |  | ||||||
| 
 |  | ||||||
| ```js |  | ||||||
| module.exports = { |  | ||||||
|   presets: ['@vant/cli/preset'], |  | ||||||
| }; |  | ||||||
| ``` |  | ||||||
| 
 |  | ||||||
| `@vant/cli/preset`中默认包含了以下插件: |  | ||||||
| 
 |  | ||||||
| - @babel/preset-env(不含 core-js) |  | ||||||
| - @babel/preset-typescript |  | ||||||
| - @babel/plugin-transform-object-assign |  | ||||||
| - @babel/plugin-proposal-optional-chaining |  | ||||||
| - @babel/plugin-proposal-nullish-coalescing-operator |  | ||||||
| - @vue/babel-preset-jsx |  | ||||||
| 
 |  | ||||||
| ## Postcss | ## Postcss | ||||||
| 
 | 
 | ||||||
| 通过根目录下的`postcss.config.js`文件可以对 Postcss 进行配置。 | 通过根目录下的`postcss.config.js`文件可以对 Postcss 进行配置。 | ||||||
| 
 | 
 | ||||||
| ### 默认配置 | ### 默认配置 | ||||||
| 
 | 
 | ||||||
| `vant-cli`中默认的 Postcss 配置如下: | `vant-cli` 中默认的 Postcss 配置如下: | ||||||
| 
 | 
 | ||||||
| ```js | ```js | ||||||
| module.exports = { | module.exports = { | ||||||
| @ -378,7 +353,7 @@ module.exports = { | |||||||
| 
 | 
 | ||||||
| ## browserslist | ## browserslist | ||||||
| 
 | 
 | ||||||
| 推荐在`package.json`文件里添加 browserslist 字段,这个值会被`@babel/preset-env`和`autoprefixer`用来确定目标浏览器的版本,保证编译后代码的兼容性。 | 推荐在 `package.json` 文件里添加 browserslist 字段,这个值会被 `autoprefixer` 用来确定目标浏览器的版本,保证编译后代码的兼容性。 | ||||||
| 
 | 
 | ||||||
| 在移动端浏览器中使用,可以添加如下配置: | 在移动端浏览器中使用,可以添加如下配置: | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -14,7 +14,6 @@ project | |||||||
| │   ├─ home.md       # 文档首页 | │   ├─ home.md       # 文档首页 | ||||||
| │   └─ changelog.md  # 更新日志 | │   └─ changelog.md  # 更新日志 | ||||||
| │ | │ | ||||||
| ├─ babel.config.js    # Babel 配置文件 |  | ||||||
| ├─ vant.config.mjs    # Vant Cli 配置文件 | ├─ vant.config.mjs    # Vant Cli 配置文件 | ||||||
| ├─ package.json | ├─ package.json | ||||||
| └─ README.md | └─ README.md | ||||||
|  | |||||||
| @ -21,8 +21,7 @@ | |||||||
|     "cjs", |     "cjs", | ||||||
|     "site", |     "site", | ||||||
|     "template", |     "template", | ||||||
|     "bin.js", |     "bin.js" | ||||||
|     "preset.cjs" |  | ||||||
|   ], |   ], | ||||||
|   "keywords": [ |   "keywords": [ | ||||||
|     "vant" |     "vant" | ||||||
| @ -49,7 +48,6 @@ | |||||||
|   }, |   }, | ||||||
|   "dependencies": { |   "dependencies": { | ||||||
|     "@babel/core": "^7.16.0", |     "@babel/core": "^7.16.0", | ||||||
|     "@babel/preset-env": "^7.16.0", |  | ||||||
|     "@babel/preset-typescript": "^7.16.0", |     "@babel/preset-typescript": "^7.16.0", | ||||||
|     "@docsearch/css": "3.0.0-alpha.41", |     "@docsearch/css": "3.0.0-alpha.41", | ||||||
|     "@docsearch/js": "3.0.0-alpha.41", |     "@docsearch/js": "3.0.0-alpha.41", | ||||||
|  | |||||||
| @ -1,3 +0,0 @@ | |||||||
| const babelConfig = require('./cjs/babel.config.cjs'); |  | ||||||
| 
 |  | ||||||
| module.exports = (api, options) => babelConfig(api, options); |  | ||||||
| @ -1,6 +1,6 @@ | |||||||
|  | import fse from 'fs-extra'; | ||||||
| import execa from 'execa'; | import execa from 'execa'; | ||||||
| import { join, relative } from 'path'; | import { join, relative } from 'path'; | ||||||
| import fse from 'fs-extra'; |  | ||||||
| import { clean } from './clean.js'; | import { clean } from './clean.js'; | ||||||
| import { CSS_LANG } from '../common/css.js'; | import { CSS_LANG } from '../common/css.js'; | ||||||
| import { ora, consola } from '../common/logger.js'; | import { ora, consola } from '../common/logger.js'; | ||||||
| @ -27,12 +27,13 @@ import { | |||||||
|   setModuleEnv, |   setModuleEnv, | ||||||
|   setBuildTarget, |   setBuildTarget, | ||||||
| } from '../common/index.js'; | } from '../common/index.js'; | ||||||
|  | import type { Format } from 'esbuild'; | ||||||
| 
 | 
 | ||||||
| const { remove, copy, readdir, existsSync } = fse; | const { remove, copy, readdir, existsSync } = fse; | ||||||
| 
 | 
 | ||||||
| async function compileFile(filePath: string) { | async function compileFile(filePath: string, format: Format) { | ||||||
|   if (isScript(filePath)) { |   if (isScript(filePath)) { | ||||||
|     return compileScript(filePath); |     return compileScript(filePath, format); | ||||||
|   } |   } | ||||||
|   if (isStyle(filePath)) { |   if (isStyle(filePath)) { | ||||||
|     return compileStyle(filePath); |     return compileStyle(filePath); | ||||||
| @ -69,12 +70,14 @@ async function preCompileDir(dir: string) { | |||||||
|   ); |   ); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| async function compileDir(dir: string) { | async function compileDir(dir: string, format: Format) { | ||||||
|   const files = await readdir(dir); |   const files = await readdir(dir); | ||||||
|   await Promise.all( |   await Promise.all( | ||||||
|     files.map((filename) => { |     files.map((filename) => { | ||||||
|       const filePath = join(dir, filename); |       const filePath = join(dir, filename); | ||||||
|       return isDir(filePath) ? compileDir(filePath) : compileFile(filePath); |       return isDir(filePath) | ||||||
|  |         ? compileDir(filePath, format) | ||||||
|  |         : compileFile(filePath, format); | ||||||
|     }) |     }) | ||||||
|   ); |   ); | ||||||
| } | } | ||||||
| @ -86,13 +89,13 @@ async function copySourceCode() { | |||||||
| async function buildESMOutputs() { | async function buildESMOutputs() { | ||||||
|   setModuleEnv('esmodule'); |   setModuleEnv('esmodule'); | ||||||
|   setBuildTarget('package'); |   setBuildTarget('package'); | ||||||
|   await compileDir(ES_DIR); |   await compileDir(ES_DIR, 'esm'); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| async function buildCJSOutputs() { | async function buildCJSOutputs() { | ||||||
|   setModuleEnv('commonjs'); |   setModuleEnv('commonjs'); | ||||||
|   setBuildTarget('package'); |   setBuildTarget('package'); | ||||||
|   await compileDir(LIB_DIR); |   await compileDir(LIB_DIR, 'cjs'); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| async function buildTypeDeclarations() { | async function buildTypeDeclarations() { | ||||||
|  | |||||||
| @ -14,6 +14,7 @@ export const TEST_REGEXP = new RegExp('\\' + sep + 'test$'); | |||||||
| export const ASSET_REGEXP = /\.(png|jpe?g|gif|webp|ico|jfif|svg|woff2?|ttf)$/i; | export const ASSET_REGEXP = /\.(png|jpe?g|gif|webp|ico|jfif|svg|woff2?|ttf)$/i; | ||||||
| export const STYLE_REGEXP = /\.(css|less|scss)$/; | export const STYLE_REGEXP = /\.(css|less|scss)$/; | ||||||
| export const SCRIPT_REGEXP = /\.(js|ts|jsx|tsx)$/; | export const SCRIPT_REGEXP = /\.(js|ts|jsx|tsx)$/; | ||||||
|  | export const JSX_REGEXP = /\.(j|t)sx$/; | ||||||
| export const ENTRY_EXTS = ['js', 'ts', 'tsx', 'jsx', 'vue']; | export const ENTRY_EXTS = ['js', 'ts', 'tsx', 'jsx', 'vue']; | ||||||
| 
 | 
 | ||||||
| export function removeExt(path: string) { | export function removeExt(path: string) { | ||||||
| @ -46,33 +47,14 @@ export function getComponents() { | |||||||
|     ); |     ); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export function isDir(dir: string) { | export const isDir = (dir: string) => lstatSync(dir).isDirectory(); | ||||||
|   return lstatSync(dir).isDirectory(); | export const isDemoDir = (dir: string) => DEMO_REGEXP.test(dir); | ||||||
| } | export const isTestDir = (dir: string) => TEST_REGEXP.test(dir); | ||||||
| 
 | export const isAsset = (path: string) => ASSET_REGEXP.test(path); | ||||||
| export function isDemoDir(dir: string) { | export const isSfc = (path: string) => SFC_REGEXP.test(path); | ||||||
|   return DEMO_REGEXP.test(dir); | export const isStyle = (path: string) => STYLE_REGEXP.test(path); | ||||||
| } | export const isScript = (path: string) => SCRIPT_REGEXP.test(path); | ||||||
| 
 | export const isJsx = (path: string) => JSX_REGEXP.test(path); | ||||||
| export function isTestDir(dir: string) { |  | ||||||
|   return TEST_REGEXP.test(dir); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export function isAsset(path: string) { |  | ||||||
|   return ASSET_REGEXP.test(path); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export function isSfc(path: string) { |  | ||||||
|   return SFC_REGEXP.test(path); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export function isStyle(path: string) { |  | ||||||
|   return STYLE_REGEXP.test(path); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export function isScript(path: string) { |  | ||||||
|   return SCRIPT_REGEXP.test(path); |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| const camelizeRE = /-(\w)/g; | const camelizeRE = /-(\w)/g; | ||||||
| const pascalizeRE = /(\w)(\w*)/g; | const pascalizeRE = /(\w)(\w*)/g; | ||||||
|  | |||||||
| @ -1,36 +1,56 @@ | |||||||
| import fse from 'fs-extra'; | import fse from 'fs-extra'; | ||||||
|  | import babel from '@babel/core'; | ||||||
|  | import esbuild, { type Format } from 'esbuild'; | ||||||
| import { sep } from 'path'; | import { sep } from 'path'; | ||||||
| import { transformAsync } from '@babel/core'; | import { isJsx, replaceExt } from '../common/index.js'; | ||||||
| import { replaceExt } from '../common/index.js'; |  | ||||||
| import { replaceCSSImportExt } from '../common/css.js'; | import { replaceCSSImportExt } from '../common/css.js'; | ||||||
| import { replaceScriptImportExt } from './get-deps.js'; | import { replaceScriptImportExt } from './get-deps.js'; | ||||||
| 
 | 
 | ||||||
| const { readFileSync, removeSync, outputFileSync } = fse; | const { readFileSync, removeSync, outputFileSync } = fse; | ||||||
| 
 | 
 | ||||||
| export async function compileScript(filePath: string): Promise<void> { | export async function compileScript( | ||||||
|   return new Promise((resolve, reject) => { |   filePath: string, | ||||||
|     if (filePath.includes('.d.ts')) { |   format: Format | ||||||
|       resolve(); | ): Promise<void> { | ||||||
|       return; |   if (filePath.includes('.d.ts')) { | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   let code = readFileSync(filePath, 'utf-8'); | ||||||
|  | 
 | ||||||
|  |   if (!filePath.includes(`${sep}style${sep}`)) { | ||||||
|  |     code = replaceCSSImportExt(code); | ||||||
|  |   } | ||||||
|  |   code = replaceScriptImportExt(code, '.vue', ''); | ||||||
|  | 
 | ||||||
|  |   if (isJsx(filePath)) { | ||||||
|  |     const babelResult = await babel.transformAsync(code, { | ||||||
|  |       filename: filePath, | ||||||
|  |       babelrc: false, | ||||||
|  |       presets: ['@babel/preset-typescript'], | ||||||
|  |       plugins: [ | ||||||
|  |         [ | ||||||
|  |           '@vue/babel-plugin-jsx', | ||||||
|  |           { | ||||||
|  |             enableObjectSlots: false, | ||||||
|  |           }, | ||||||
|  |         ], | ||||||
|  |       ], | ||||||
|  |     }); | ||||||
|  |     if (babelResult?.code) { | ||||||
|  |       ({ code } = babelResult); | ||||||
|     } |     } | ||||||
|  |   } | ||||||
| 
 | 
 | ||||||
|     let code = readFileSync(filePath, 'utf-8'); |   const esbuildResult = await esbuild.transform(code, { | ||||||
| 
 |     loader: 'ts', | ||||||
|     if (!filePath.includes(`${sep}style${sep}`)) { |     target: 'es2016', | ||||||
|       code = replaceCSSImportExt(code); |     format, | ||||||
|     } |  | ||||||
|     code = replaceScriptImportExt(code, '.vue', ''); |  | ||||||
| 
 |  | ||||||
|     transformAsync(code, { filename: filePath }) |  | ||||||
|       .then((result) => { |  | ||||||
|         if (result) { |  | ||||||
|           const jsFilePath = replaceExt(filePath, '.js'); |  | ||||||
| 
 |  | ||||||
|           removeSync(filePath); |  | ||||||
|           outputFileSync(jsFilePath, result.code); |  | ||||||
|           resolve(); |  | ||||||
|         } |  | ||||||
|       }) |  | ||||||
|       .catch(reject); |  | ||||||
|   }); |   }); | ||||||
|  | 
 | ||||||
|  |   ({ code } = esbuildResult); | ||||||
|  | 
 | ||||||
|  |   const jsFilePath = replaceExt(filePath, '.js'); | ||||||
|  |   removeSync(filePath); | ||||||
|  |   outputFileSync(jsFilePath, code); | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,11 +0,0 @@ | |||||||
| module.exports = { |  | ||||||
|   presets: [ |  | ||||||
|     [ |  | ||||||
|       '@vant/cli/preset.cjs', |  | ||||||
|       { |  | ||||||
|         loose: process.env.BUILD_TARGET === 'package', |  | ||||||
|         enableObjectSlots: false, |  | ||||||
|       }, |  | ||||||
|     ], |  | ||||||
|   ], |  | ||||||
| }; |  | ||||||
							
								
								
									
										912
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										912
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user