import react from '@vitejs/plugin-react' ; import analyzer from 'rollup-plugin-visualizer' ; import * as path from 'path' ; import { all } from 'deepmerge' ; import { isObject } from 'lodash' ; import tsChecker from 'vite-plugin-ts-types' ; import { Context , ITaskConfig } from 'build-scripts' ; import type { TransformOptions } from '@babel/core' ; import eslintReport from 'vite-plugin-eslint-report' ; import { normalizePath } from 'vite' ; import type { InlineConfig , BuildOptions , PluginOption } from 'vite' ; import { recordMap } from './config' ; import { externalsPlugin , importPlugin , polyfillPlugin , serverHistoryPlugin , htmlPlugin , ignoreHtmlPlugin , mockPlugin , ImportDeclarations , } from '../plugins' ; type Option = BuildOptions & InlineConfig ; const getAnalyzer = ( config ) => { if ( ! config . plugins . get ( 'webpack-bundle-analyzer' ) ) return ; return analyzer ( { open : true , brotliSize : true , filename : 'ice-stats.html' } ) ; } ; const getWebpackConfig = ( context ) => { const configArr = context . getWebpackConfig ( ) ; return configArr [ 0 ] ; } ; const arrayMerge = ( destinationArray , sourceArray ) => { return [ ... ( destinationArray || [ ] ) , ... ( sourceArray || [ ] ) ] ; } ; const isBuild = ( command ) => command === 'build' ; const getHtmlPlugin = ( context ) => { const { getValue , userConfig , rootDir , command } = context ; type Opt = { template : string ; filename : string ; inject ? : boolean ; templateParameters ? : Record < string , string > ; favicon ? : string ; minify ? : boolean ; excludeChunks ? : string [ ] ; } ; const isMpa = userConfig . mpa as boolean ; const ssr = userConfig . ssr as boolean ; if ( ! isMpa ) { return htmlPlugin ( { entry : userConfig . entry as string , template : path . resolve ( rootDir , 'public' , 'index.html' ) , filename : 'index.html' , rootDir , ssr , command , } ) ; } const pages = { index : { template : path . resolve ( rootDir , 'public' , 'index.html' ) , filename : 'index.html' , } , ... getValue ( 'MPA_PAGES' ) , } as Record < string , Opt > ; const entries = userConfig . entry as Record < string , string [ ] > ; const mpaHtmlPlugins = Object . keys ( entries ) . map ( entryName => { const singlePage = pages [ entryName ] ?? pages . index ; if ( entryName === 'index' ) { return htmlPlugin ( { ... singlePage , entry : entries [ entryName ] [ 0 ] , rootDir , ssr , command , } ) ; } return htmlPlugin ( { ... singlePage , entry : entries [ entryName ] [ 0 ] , rootDir , ssr , command , } ) ; } ) ; return mpaHtmlPlugins ; } ; type BabelPreset = [ string , Record < string , any > ] ; const getPluginReact = ( context ) : PluginOption [ ] => { const { userConfig , originalUserConfig , command } = context ; const fastRefresh = userConfig . fastRefresh && command === 'start' ; const jsxRuntimeConfig = userConfig . babelPresets && ( userConfig . babelPresets as BabelPreset [ ] ) . find ( ( [ pluginName , pluginOptions ] ) => pluginName . includes ( '@babel/preset-react' ) && pluginOptions ?. runtime === 'automatic' ) ; const babelPlugins = userConfig . babelPlugins as TransformOptions [ 'plugins' ] ; if ( fastRefresh || babelPlugins . length > 0 || jsxRuntimeConfig || originalUserConfig . babelPresets ) { return react ( { exclude : [ /node_modules/ , /[\\/]\.ice[\\/]/ ] , fastRefresh , jsxRuntime : jsxRuntimeConfig ? 'automatic' : 'classic' , parserPlugins : [ 'decorators-legacy' ] , babel : { plugins : babelPlugins , presets : originalUserConfig . babelPresets as TransformOptions [ 'presets' ] , } } ) ; } return [ ] ; } ; const getRedirectImport = ( context ) => { const importDeclarations = context . getValue ( 'importDeclarations' ) || { } ; const redirects = Object . keys ( importDeclarations ) . map ( ( name ) => ( { name , ... importDeclarations [ name ] } ) ) as ImportDeclarations [ ] ; return redirects ; } ; /**
 * Exposed
 */ export const wp2vite = ( context ) : InlineConfig => { const { commandArgs = { } , userConfig , originalUserConfig , rootDir , command } = context ; const config = getWebpackConfig ( context ) ; let viteConfig = { configFile : false , root : rootDir , plugins : [ userConfig . mock && mockPlugin ( ( userConfig . mock as { exclude ? : string [ ] ; } ) ?. exclude ) , getAnalyzer ( config . chainConfig ) , externalsPlugin ( userConfig . externals as any ) , importPlugin ( { source : 'ice' , redirectImports : getRedirectImport ( context ) } ) , serverHistoryPlugin ( config . chainConfig . devServer . get ( 'historyApiFallback' ) ) , getHtmlPlugin ( context ) , userConfig . tsChecker && tsChecker ( ) , polyfillPlugin ( { value : originalUserConfig . polyfill as any , browserslist : userConfig . browserslist as any , hash : userConfig . hash as boolean , outputAssetsPath : userConfig . outputAssetsPath as any , rootDir , } ) , userConfig . ignoreHtmlTemplate ? ignoreHtmlPlugin ( rootDir ) : null , ... getPluginReact ( context ) , ] . filter ( Boolean ) , } ; if ( userConfig . eslint !== false ) { let eslintOptions = { ignoreInitial : false } ; if ( userConfig . eslint === true ) { eslintOptions . ignoreInitial = true ; } else { eslintOptions = { ... eslintOptions , ... ( userConfig . eslint as Object ) , } ; } viteConfig . plugins . push ( eslintReport ( eslintOptions ) ) ; } if ( isObject ( userConfig . vite ) ) { viteConfig = all ( [ recordMap ( config . chainConfig , context ) , viteConfig , userConfig . vite ] , { arrayMerge } ) ; } const devServerConfig = { port : commandArgs . port || 3333 , host : commandArgs . host || '0.0.0.0' , https : commandArgs . https || false , } ; const entryExts = /(\.ts|\.tsx|\.js|\.jsx)$/i ; const getAnalysisEntries = ( ) => { let appEntry = userConfig . entry ; if ( ! userConfig . mpa ) { if ( Array . isArray ( appEntry ) ) { appEntry = { index : appEntry , } ; } else if ( typeof appEntry === 'string' ) { appEntry = { index : [ appEntry ] , } ; } } const entries = Object . keys ( appEntry ) . map ( e => { const url = appEntry [ e ] [ 0 ] ; return normalizePath ( entryExts . exec ( url ) ? url : `${ url }.*` ) ; } ) ; return entries ; } ; if ( ! isBuild ( command ) ) { return all ( [ { mode : 'development' , optimizeDeps : { entries : getAnalysisEntries ( ) , include : [ 'react-app-renderer' , 'create-app-shared' ] , } , server : devServerConfig , } , viteConfig , ] , { arrayMerge } ) ; } else { return all ( [ { build : { commonjsOptions : { exclude : [ 'react-app-renderer' , 'create-app-shared' ] , } , rollupOptions : { context : undefined , } , } , } , viteConfig ] , { arrayMerge } ) ; } } ;