我正在将应用程序迁移到 Angular 13 和 webpack 5(+ 开发服务器)。
迁移到这些版本后,应用程序无法启动。
app.main.ts:
platformBrowserDynamic().bootstrapModule(AppModule)
.then((success) => console.log(`Application started`))
.catch((err) => console.error(err));
每当
bootstrapModule(AppModule)
运行时,我在浏览器控制台中得到,而不是模块引导成功:
TypeError: this.input.charCodeAt is not a function
at PlainCharacterCursor.charAt (compiler.mjs?a6f7:13874:1)
at PlainCharacterCursor.updatePeek (compiler.mjs?a6f7:13893:1)
at PlainCharacterCursor.init (compiler.mjs?a6f7:13852:1)
at new _Tokenizer (compiler.mjs?a6f7:13119:1)
at tokenize (compiler.mjs?a6f7:13066:1)
at HtmlParser.parse (compiler.mjs?a6f7:14068:1)
at HtmlParser.parse (compiler.mjs?a6f7:14456:1)
at parseTemplate (compiler.mjs?a6f7:18533:1)
at parseJitTemplate (compiler.mjs?a6f7:19697:1)
at CompilerFacadeImpl.compileComponent (compiler.mjs?a6f7:19466:43)
eval @ app.main.ts?170f:10
我已经尝试过Uncaught TypeError: this._input.charCodeAt is not a function的建议,但他们没有帮助我。模板 URL 已正确命名,我的开发 webpack 配置中未使用 raw-loader。
我已将 try/catch 添加到
@angular/compiler/fesm2020/compiler.mjs
_Tokenizer 构造函数,如下所示:
try {
// original code of constructor
} catch (exc) {
console.log('[Tokenizer Error]: ' + _file && JSON.stringify(_file, null, 2));
throw(exc);
}
得到如下结果:
{
"content": {
"default": "html content of main component"
},
"url": "ng:///MainComponent/template.html"
}
我看到在
PlainCharacterCoursor
中输入是这样分配的:this.input = fileOrCursor.content;
。稍后此输入在 charAt
中使用,如下所示:
charAt(pos) {
return this.input.charCodeAt(pos);
}
在我看来,这里的问题是
content
是一个嵌套对象,default
字段包含 HTML 内容,而不是 content 是具有所述 HTML 内容的字符串值的键。
为了开发,我运行:
yarn run webpack serve -- --stats-error-details --config {webpack_config} --progress --profile
package.json 中的依赖列表:
...
"dependencies": {
"@angular/animations": "^13.3.12",
"@angular/cdk": "13.3.9",
"@angular/common": "13.3.12",
"@angular/compiler": "13.3.12",
"@angular/core": "13.3.12",
"@angular/forms": "13.3.12",
"@angular/material": "^13.3.9",
"@angular/platform-browser": "13.3.12",
"@angular/platform-browser-dynamic": "13.3.12",
"@angular/router": "13.3.12",
"@fortawesome/angular-fontawesome": "^0.10.2",
"@fortawesome/fontawesome-svg-core": "^6.2.0",
"@fortawesome/free-solid-svg-icons": "^6.2.0",
"@ng-bootstrap/ng-bootstrap": "^11.0.1",
"@ngx-translate/core": "^14.0.0",
"@ngx-translate/http-loader": "^7.0.0",
"@popperjs/core": "^2.11.6",
"bootstrap": "5.2.3",
"brace": "^0.11.1",
"chartist": "^1.3.0",
"core-js": "3.26.1",
"fast-xml-parser": "^4.0.11",
"font-awesome": "4.7.0",
"jquery": "3.6.1",
"ng-jhipster": "0.16.0",
"ng2-ckeditor": "1.3.6",
"ngx-cookie": "6.0.0",
"ngx-infinite-scroll": "13.0.2",
"ngx-webstorage": "9.0.0",
"postcss": "8.4.14",
"reflect-metadata": "0.1.13",
"rxjs": "^7.4.0",
"sass": "^1.59.3",
"save": "^2.9.0",
"swagger-ui": "2.2.10",
"tether": "2.0.0",
"zone.js": "~0.11.8"
},
"devDependencies": {
"@angular-devkit/build-angular": "~13.3.11",
"@angular-eslint/builder": "13.5.0",
"@angular-eslint/eslint-plugin": "13.5.0",
"@angular-eslint/eslint-plugin-template": "13.5.0",
"@angular-eslint/schematics": "13.5.0",
"@angular-eslint/template-parser": "13.5.0",
"@angular/cli": "13.3.11",
"@angular/compiler-cli": "^13.3.12",
"@ngtools/webpack": "13.3.11",
"@types/ckeditor": "4.9.10",
"@types/jasmine": "4.3.1",
"@types/jquery": "^3.5.16",
"@types/nanoscroller": "^0.8.6",
"@types/node": "18.15.11",
"@typescript-eslint/eslint-plugin": "5.27.1",
"@typescript-eslint/parser": "5.27.1",
"angular2-template-loader": "0.6.2",
"browser-sync": "2.29.0",
"browser-sync-webpack-plugin": "2.3.0",
"copy-webpack-plugin": "11.0.0",
"css-loader": "6.7.3",
"dotenv-webpack": "^8.0.1",
"eslint": "^8.17.0",
"eslint-webpack-plugin": "^4.0.0",
"exports-loader": "4.0.0",
"file-loader": "6.2.0",
"generator-jhipster": "7.9.3",
"html-loader": "4.2.0",
"html-webpack-plugin": "5.5.0",
"jasmine-core": "4.5.0",
"karma": "6.4.1",
"karma-chrome-launcher": "3.1.1",
"karma-coverage": "2.2.0",
"karma-intl-shim": "1.0.3",
"karma-jasmine": "5.1.0",
"karma-junit-reporter": "2.0.1",
"karma-notify-reporter": "1.3.0",
"karma-phantomjs-launcher": "1.0.4",
"karma-remap-istanbul": "0.6.0",
"karma-sourcemap-loader": "0.4.0",
"karma-webpack": "5.0.0",
"merge-jsons-webpack-plugin": "2.0.1",
"mini-css-extract-plugin": "2.7.2",
"phantomjs-prebuilt": "2.1.16",
"postcss-loader": "7.1.0",
"proxy-middleware": "0.15.0",
"rimraf": "3.0.2",
"sass-loader": "^13.2.1",
"sourcemap-istanbul-instrumenter-loader": "0.2.0",
"style-loader": "3.3.2",
"to-string-loader": "1.2.0",
"ts-loader": "9.4.2",
"tslib": "2.4.1",
"typescript": "4.6.4",
"webpack": "5.76.2",
"webpack-cli": "5.0.1",
"webpack-dev-server": "4.13.1",
"webpack-merge": "5.8.0",
"webpack-notifier": "1.15.0",
"workbox-webpack-plugin": "6.5.4",
"write-file-webpack-plugin": "4.5.1",
"xml2js": "0.4.23"
},
...
Webpack 开发服务器配置:
devServer: {
static: './target/www',
port: 9060,
devMiddleware: {
writeToDisk: true
},
proxy: [{
context: [
/* jhipster-needle-add-entity-to-webpack - JHipster will add entity api paths here */
'/api',
'/management',
'/swagger-resources',
'/v2/api-docs',
'/h2-console',
'/auth'
],
target: 'http://127.0.0.1:8080',
secure: false
}],
watchFiles: {
options:{
ignored: /node_modules/
}
}
},
Webpack与HTML加载相关的配置部分:
const HtmlWebpackPlugin = require('html-webpack-plugin');
...
module: {
rules: [
{
test: /\.html$/,
use: [
{
loader: 'html-loader',
options: {
minimize: false
}
}
],
exclude: [path_to_index_html_here]
}
]
}
...
plugins: [
new HtmlWebpackPlugin({
template: path_to_index_html_here,
inject: 'body'
})
]
如果有任何用处,这里还有使用 angular2-template 加载 TS 文件:
rules: [{
test: /\.ts$/,
use: [
{
loader: 'ts-loader'
},
{
loader: 'angular2-template-loader'
}
],
exclude: [path_to_generator_jhipster_in_modules]
}
]