import { REG_VUE } from '@tarojs/helper' ; import { internalComponents , toCamelCase , capitalize } from '@tarojs/shared/dist/template' ; import { getLoaderMeta } from './loader-meta' ; import { getVueLoaderPath } from './index' ; import type { IPluginContext } from '@tarojs/service' ; import type { RootNode , TemplateChildNode , ElementNode , AttributeNode , DirectiveNode , SimpleExpressionNode } from '@vue/compiler-core' ; import type { IConfig } from './index' ; const CUSTOM_WRAPPER = 'custom-wrapper' ; type MiniConfig = IConfig [ 'mini' ] ; export function modifyMiniWebpackChain ( _ctx , chain , data , config ) { setVueLoader ( chain , data , config ) ; setLoader ( chain ) ; setDefinePlugin ( chain ) ; } function setVueLoader ( chain , data , config ) { const vueLoaderPath = getVueLoaderPath ( ) ; const { VueLoaderPlugin } = require ( vueLoaderPath ) ; chain . plugin ( 'vueLoaderPlugin' ) . use ( VueLoaderPlugin ) ; const vueLoaderOption = { optimizeSSR : false , transformAssetUrls : { video : [ 'src' , 'poster' ] , 'live-player' : 'src' , audio : 'src' , source : 'src' , image : 'src' , 'cover-image' : 'src' } , compilerOptions : { } } ; if ( config ?. compilerOptions ) { vueLoaderOption . compilerOptions = Object . assign ( { } , config . compilerOptions ) ; } vueLoaderOption . compilerOptions . nodeTransforms ||= [ ] ; vueLoaderOption . compilerOptions . nodeTransforms . unshift ( ( node ) => { if ( node . type === 1 ) { node = node as ElementNode ; const nodeName = node . tag ; if ( capitalize ( toCamelCase ( nodeName ) ) in internalComponents ) { if ( node . tagType === 1 ) { node . tagType = 0 ; } data . componentConfig . includes . add ( nodeName ) ; } if ( nodeName === CUSTOM_WRAPPER ) { node . tagType = 0 ; data . componentConfig . thirdPartyComponents . set ( CUSTOM_WRAPPER , new Set ( ) ) ; } const usingComponent = data . componentConfig . thirdPartyComponents . get ( nodeName ) ; if ( usingComponent != null ) { node . props . forEach ( prop => { if ( prop . type === 6 ) { usingComponent . add ( ( prop as AttributeNode ) . name ) ; } else if ( ( prop as any ) . type === 7 ) { prop = prop as DirectiveNode ; if ( prop . arg ?. type === 4 ) { let value = ( prop . arg as SimpleExpressionNode ) . content ; if ( prop . name === 'on' ) { value = `on${ value }` ; } usingComponent . add ( value ) ; } } } ) ; } } } ) ; chain . module . rule ( 'vue' ) . test ( REG_VUE ) . use ( 'vueLoader' ) . loader ( vueLoaderPath ) . options ( vueLoaderOption ) ; } function setLoader ( chain ) { chain . plugin ( 'miniPlugin' ) . tap ( args => { args [ 0 ] . loaderMeta = getLoaderMeta ( ) ; return args ; } ) ; } function setDefinePlugin ( chain ) { chain . plugin ( 'definePlugin' ) . tap ( args => { args [ 0 ] . ENABLE_ADJACENT_HTML = true ; args [ 0 ] . ENABLE_CLONE_NODE = true ; args [ 0 ] . ENABLE_TEMPLATE_CONTENT = true ; args [ 0 ] . ENABLE_MUTATION_OBSERVER = true ; return args ; } ) ; }