Angular 11升级至12后启动报错:rootPath undefined不是程序文件
Angular 11升级至12后的编译错误及组件适配问题
问题场景
执行升级命令 ng update @angular/core@12 @angular/cli@12 完成版本升级后,运行 yarn start 触发编译错误:
ERROR in The given rootPath undefined is not a file of the program
尝试将 angular-sortablejs 替换为 ngx-sortablejs 后,项目内大量模块和组件出现报错。以下是项目的核心配置文件:
package.json
{ "dependencies": { "@agm/core": "^3.0.0-beta.0", "@agm/drawing": "^3.0.0-beta.0", "@angular/animations": "^12.2.16", "@angular/cdk": "^11.2.13", "@angular/common": "^12.2.16", "@angular/compiler": "^12.2.16", "@angular/core": "^12.2.16", "@angular/forms": "^12.2.16", "@angular/http": "^6.1.0", "@angular/material": "^11.2.13", "@angular/platform-browser": "^12.2.16", "@angular/platform-browser-dynamic": "^12.2.16", "@angular/platform-server": "^12.2.16", "@angular/router": "^12.2.16", "@aspnet/signalr": "^1.0.2", "@devexpress/analytics-core": "^19.2.4", "@fancyapps/fancybox": "^3.1.25", "@kolkov/angular-editor": "^0.13.1", "@ng-plus/signature-pad": "0.0.5", "@progress/kendo-angular-buttons": "^5.2.2", "@progress/kendo-angular-charts": "^4.1.4", "@progress/kendo-angular-common": "^1.2.2", "@progress/kendo-angular-dateinputs": "^4.2.1", "@progress/kendo-angular-dropdowns": "^4.2.4", "@progress/kendo-angular-excel-export": "^3.1.0", "@progress/kendo-angular-grid": "^4.6.3", "@progress/kendo-angular-inputs": "^6.4.1", "@progress/kendo-angular-intl": "^2.0.1", "@progress/kendo-angular-l10n": "^2.0.1", "@progress/kendo-angular-layout": "^4.2.0", "@progress/kendo-angular-menu": "^2.0.1", "@progress/kendo-angular-pdf-export": "^2.0.2", "@progress/kendo-angular-popup": "^3.0.5", "@progress/kendo-angular-tooltip": "^2.1.2", "@progress/kendo-angular-treeview": "^4.1.0", "@progress/kendo-angular-upload": "^5.2.0", "@progress/kendo-data-query": "^1.5.2", "@progress/kendo-drawing": "^1.6.0", "@progress/kendo-theme-default": "4.43.0", "abp-ng2-module": "^3.2.3", "abp-web-resources": "^3.8.4", "angular-oauth2-oidc": "^4.0.2", "angular-sortablejs": "^2.6.0", "angular2-counto": "^1.2.5", "angular2-uuid": "^1.1.1", "animate.css": "3.6.1", "autosize": "^4.0.0", "b64-to-blob": "^1.2.19", "block-ui": "^2.70.1", "blueimp-file-upload": "^9.22.0", "bootstrap": "^4.1.3", "bootstrap-daterangepicker": "^3.0.3", "bootstrap-hover-dropdown": "^2.2.1", "bootstrap-markdown": "^2.10.0", "bootstrap-maxlength": "^1.6.0", "bootstrap-notify": "^3.1.3", "bootstrap-select": "1.13.1", "bootstrap-switch": "^3.3.4", "bootstrap-timepicker": "^0.5.2", "bootstrap-touchspin": "^4.2.5", "bootstrap4-datetimepicker": "^5.2.3", "bower": "*", "chart.js": "^2.6.0", "chartist": "^0.11.0", "clone": "^2.1.2", "codelyzer": "^6.0.0", "compare-versions": "^3.4.0", "core-js": "^2.5.7", "css-star-rating": "^1.2.4", "css-toggle-switch": "^4.0.3", "d3": "^5.5.0", "detect-zoom": "^1.0.2", "devexpress-dashboard": "^19.2.4", "devexpress-reporting-angular": "^19.2.4", "devextreme": "^19.2.4", "dropzone": "^5.5.1", "easy-pie-chart": "^2.1.7", "famfamfam-flags": "^1.0.0", "flot": "^0.8.0-alpha", "font-awesome": "^4.7.0", "gmaps": "^0.4.24", "inputmask": "^4.0.0", "ion-rangeslider": "^2.3.1", "jasmine-spec-reporter": "~5.0.0", "jquery": "^3.2.1", "jquery-form": "^4.2.1", "jquery-migrate": "^3.0.0", "jquery-mousewheel": "^3.1.13", "jquery-slimscroll": "^1.3.8", "jquery-sparkline": "^2.4.0", "jquery-validation": "^1.15.1", "jquery.counterup": "^2.1.0", "jquery.flot.tooltip": "^0.9.0", "jquery.inputmask": "^3.3.4", "jquery.uniform": "^4.2.0", "jqueryui": "^1.11.1", "jqvmap": "^1.5.1", "js-cookie": "^2.1.4", "js-url": "^2.3.0", "json2": "*", "jstree": "^3.3.4", "karma": "^6.4.0", "localforage": "^1.7.2", "lodash": "^4.17.4", "malihu-custom-scrollbar-plugin": "^3.1.5", "moment": "^2.24.0", "moment-timezone": "^0.5.21", "morris.js": "^0.5.0", "mustache": "^2.3.0", "ng-recaptcha": "^4.0.0-beta.1", "ng2-file-upload": "^1.3.0", "ng2modules-easypiechart": "^0.0.4", "ng2modules-flot": "^0.0.1", "ngx-bootstrap": "^9.0.0", "ngx-device-detector": "^1.4.5", "ngx-mask": "^6.1.3", "ngx-webcam": "^0.2.6", "pace-progress": "^1.0.2", "popper.js": "^1.12.5", "primeicons": "1.0.0-beta.10", "primeng": "6.0.2", "prismjs": "^1.15.0", "push.js": "1.0.7", "quill": "^1.3.7", "rangeslider.js": "^2.3.1", "raphael": "^2.2.7", "rtl-detect": "^1.0.0", "rxjs": "^6.5.5", "sass": "^1.54.0", "select2": "^4.0.5", "select2-bootstrap-theme": "0.1.0-beta.10", "simple-line-icons": "^2.4.1", "socicon": "^3.0.5", "sortablejs": "^1.7.0", "spin.js": "^2.3.2", "summernote": "^0.8.6", "sweetalert": "^2.0.8", "tether": "^1.4.0", "timeago": "^1.6.1", "toastr": "^2.1.2", "topojson": "^3.0.2", "ts-helpers": "^1.1.2", "ts-node": "~7.0.0", "tslib": "^2.0.0", "typeahead.js": "^0.11.1", "underscore": "^1.9.1", "urijs": "^1.19.0", "uuid": "^8.3.2", "waypoints": "^4.0.1", "zone.js": "~0.11.4" }, "devDependencies": { "@angular-devkit/build-angular": "~12.2.18", "@angular/cli": "^12.2.18", "@angular/compiler-cli": "^12.2.16", "@angularclass/hmr": "^2.1.3", "@angularclass/hmr-loader": "^3.0.4", "@types/bootstrap": "^4.1.2", "@types/grecaptcha": "^2.0.35", "@types/jasmine": "~3.6.0", "@types/jasminewd2": "~2.0.2", "@types/jquery": "^3.3.5", "@types/jquery.blockui": "0.0.28", "@types/jstree": "^3.3.34", "@types/lodash": "^4.14.114", "@types/moment": "^2.13.0", "@types/moment-timezone": "^0.5.6", "@types/morris.js": "^0.5.7", "@types/node": "^12.11.1", "@types/tether": "^1.4.4", "@types/toastr": "^2.1.33", "codelyzer": "^6.0.0", "jasmine-core": "~3.6.0", "jasmine-spec-reporter": "~5.0.0", "karma-chrome-launcher": "~3.1.0", "karma-cli": "~1.0.1", "karma-coverage-istanbul-reporter": "^2.0.1", "karma-jasmine": "~4.0.0", "karma-jasmine-html-reporter": "^1.5.0", "nativescript-dev-webpack": "^0.24.1", "nswag": "^11.17.21", "protractor": "~7.0.0", "ts-node": "~7.0.0", "tslint": "^6.1.3", "typescript": "4.3.5", "yarn-upgrade-all": "^0.7.1" } }
tsconfig.json
{ "compilerOptions": { "declaration": false, "experimentalDecorators": true, "lib": [ "es2015" , "es6", "dom" ], "mapRoot": "./", "module": "esnext", "skipLibCheck": true, "moduleResolution": "node", "outDir": "../dist/out-tsc", "sourceMap": true, "target": "es2015", "typeRoots": [ "../node_modules/@types" ], "baseUrl": "./", "paths": { "@abp/*": [ "../node_modules/abp-ng2-module/dist/src/*" ], "@app/*": [ "./app/*" ], "@shared/*": [ "./shared/*" ], "@node_modules/*": [ "../node_modules/*" ], "@angular/*": [ "../node_modules/@angular/*" ] } }, "files": [ "main.ts", "polyfills.ts" ], "include": [ "../src/**/*", "../node_modules/abp-ng2-module/**/*" ] }
问题修复方案
1. 解决"rootPath undefined"编译错误
错误根源是依赖版本不匹配或编译缓存异常:
- 对齐Angular CDK和Material版本:当前@angular/cdk、@angular/material停留在11.x版本,与已升级的12.x核心包不兼容,执行命令统一版本:
yarn add @angular/cdk@12.2.16 @angular/material@12.2.16 - 清理缓存并重建项目:升级后残留的旧缓存会导致编译异常,执行:
yarn cache clean rm -rf node_modules dist yarn install yarn start - 校验tsconfig路径配置:确认
include中的../src/**/*是否匹配实际项目目录结构,若项目src目录与配置文件同级,可调整为src/**/*。
2. 适配sortable组件替换后的报错
angular-sortablejs与ngx-sortablejs的API、导入方式差异较大,需逐步调整:
- 安装兼容版本:卸载旧依赖,安装适配Angular 12的ngx-sortablejs及对应sortablejs版本:
yarn remove angular-sortablejs sortablejs yarn add ngx-sortablejs sortablejs@^1.10.0 - 修改模块导入逻辑:原
SortableModule.forRoot()的导入方式需替换为ngx-sortablejs的规范:import { SortableModule } from 'ngx-sortablejs'; @NgModule({ imports: [ // 其他模块 SortableModule.forRoot({ animation: 150 }) // 根据业务需求调整配置项 ] }) - 调整组件内的调用逻辑:
- 模板中
[sortablejs]指令用法基本一致,但自定义事件、配置项需参考ngx-sortablejs规范调整; - 若组件内直接操作Sortable实例,需通过
ViewChild获取:import { SortableComponent } from 'ngx-sortablejs'; @ViewChild(SortableComponent) sortableComponent: SortableComponent; // 获取实例 const sortableInstance = this.sortableComponent.sortable;
- 模板中
- 逐个修复报错组件:根据编译错误提示,逐一修改每个组件中与sortable相关的代码,确保API调用符合ngx-sortablejs要求。
内容的提问来源于stack exchange,提问作者Islam Eldeeb
相关产品推荐
相关产品推荐

