44 */
55
66import path from 'path'
7+ import fs from 'fs'
78import { colorconsole , readJson , logger , eventBus } from '@hap-toolkit/shared-utils'
89import { resolveEntries } from '../utils'
910
@@ -21,6 +22,8 @@ export default class ManifestWatchPlugin {
2122 constructor ( options ) {
2223 this . appRoot = options . appRoot
2324 this . root = options . root
25+ this . buildDir = options . buildDir
26+ this . entryState = options . entryState
2427 this . manifestFile = path . resolve ( this . root , 'manifest.json' )
2528 let entries = { }
2629 try {
@@ -31,32 +34,81 @@ export default class ManifestWatchPlugin {
3134 this . list = Object . keys ( entries )
3235 this . list = sort ( this . list )
3336 }
34- hasChanged ( newList ) {
35- const sorted = sort ( newList )
36- const changed = JSON . stringify ( sorted ) !== JSON . stringify ( this . list )
37+
38+ getRemovedEntries ( newList ) {
39+ const newSet = new Set ( newList )
40+ return this . list . filter ( ( key ) => ! newSet . has ( key ) )
41+ }
42+
43+ updateEntries ( entries ) {
44+ const newList = sort ( Object . keys ( entries ) )
45+ const removedEntries = this . getRemovedEntries ( newList )
46+ const changed = JSON . stringify ( newList ) !== JSON . stringify ( this . list )
3747 if ( changed ) {
38- this . list = sorted
48+ this . list = newList
49+ this . entryState && ( this . entryState . current = entries )
50+ }
51+ return {
52+ changed,
53+ removedEntries
3954 }
40- return changed
4155 }
56+
57+ removeBuildArtifacts ( entryKeys ) {
58+ if ( ! this . buildDir || ! entryKeys || entryKeys . length === 0 ) {
59+ return
60+ }
61+ entryKeys . forEach ( ( entryKey ) => {
62+ const entryDir = path . dirname ( entryKey )
63+ if ( entryDir && entryDir !== '.' ) {
64+ const targetDir = path . join ( this . buildDir , entryDir )
65+ if ( fs . existsSync ( targetDir ) ) {
66+ fs . rmSync ( targetDir , { recursive : true , force : true } )
67+ this . removeEmptyParentDirs ( path . dirname ( targetDir ) )
68+ }
69+ return
70+ }
71+
72+ ; [
73+ `${ entryKey } .js` ,
74+ `${ entryKey } .js.map` ,
75+ `${ entryKey } .css.json` ,
76+ `${ entryKey } .template.json`
77+ ] . forEach ( ( relativeFile ) => {
78+ const targetFile = path . join ( this . buildDir , relativeFile )
79+ if ( ! fs . existsSync ( targetFile ) ) {
80+ return
81+ }
82+ fs . unlinkSync ( targetFile )
83+ this . removeEmptyParentDirs ( path . dirname ( targetFile ) )
84+ } )
85+ } )
86+ }
87+
88+ removeEmptyParentDirs ( dir ) {
89+ while ( dir && dir . startsWith ( this . buildDir ) && dir !== this . buildDir ) {
90+ if ( ! fs . existsSync ( dir ) || fs . readdirSync ( dir ) . length > 0 ) {
91+ return
92+ }
93+ fs . rmdirSync ( dir )
94+ dir = path . dirname ( dir )
95+ }
96+ }
97+
4298 apply ( compiler ) {
4399 compiler . hooks . watchRun . tapAsync ( 'watch' , ( compiler , callback ) => {
44100 eventBus . emit ( PACKAGER_WATCH_START )
45101 logger . clear ( )
46102 try {
47103 const modifiedFiles = compiler . modifiedFiles
48- // 当发生变化的文件是 app.json,且 list 列表有增/删时,更新入口文件
49- // TODO 页面减少时不会移除 entry
50- // https://stackoverflow.com/a/39401288/1087831
104+ // 当发生变化的文件是 manifest.json,且入口列表有增删时,更新当前编译入口
51105 if ( modifiedFiles && modifiedFiles . has ( this . manifestFile ) ) {
52106 /** @readonly */
53107 const manifest = readJson ( this . manifestFile )
54108 const entries = resolveEntries ( manifest , this . root , this . appRoot )
55- const newList = Object . keys ( entries )
56- if ( this . hasChanged ( newList ) ) {
57- // 增删页面要修改 webpack entries
58- this . list = newList
59- compiler . options . entry = entries
109+ const { changed, removedEntries } = this . updateEntries ( entries )
110+ if ( changed ) {
111+ this . removeBuildArtifacts ( removedEntries )
60112 }
61113 }
62114 } catch ( err ) {
0 commit comments