angular – 带有AOT的延迟加载模块 – TypeError:”从NGINX提供
以下是我自己重现的dist文件:
> dist with Lazy Modules,AOT 细分: >我的dist构建,AOT和Lazy Loaded模块在使用npm包webpack-dev-server或live-server时工作正常 我正在使用官方的Angular包@ ngtools / webpack将AOT编译添加到我的Angular 5应用程序中. This article解释了如何使用@ ngtools / webpack将AOT添加到Webpack构建项目中.很简单,虽然文章没有提到到add the Lazy Load module file paths到tsconfig-aot.json所需的步骤. AOT失败了. 所有作品都很棒localhost: npm run serve 我的npm run serve命令是内存编译,资源使用npm包webpack-dev-server从内存中提供localhost. 当我部署到我的开发服务器时,编译文件存储在磁盘上,我的开发服务器使用NGINX提供资源. 我有延迟加载的模块,加载时会在Firefox中抛出这样的奇怪错误: TypeError: i0.u0275crt is not a function 这在Chrome中: ERROR TypeError: i0.?crt is not a function 通过Chrome中的错误了解更多细节,以下是抛出错误的源代码行代码: 我看到var i0的创建就是这一行: var i0 = __webpack_require__(/*! @angular/core */ "./node_modules/@angular/core/esm5/core.js"); 在我的开发服务器上,node_modules在父级别与我的dist文件夹: 我的dev服务器上的文件: 以下是从localhost提供的资源文件的比较: 这是从开发服务器提供的资源文件: 好的,所以这里有我的配置和npm包版本: webpack.config var merge = require('webpack-merge'),htmlPlugin = require('html-webpack-plugin'),revPlugin = require('webpack-rev-replace-plugin'),config = require('./build.config.json'),path = require('path'),extendedDefinePlugin = require('extended-define-webpack-plugin'),webpackDelPlugin = require('webpack-del-plugin'),openBrowserPlugin = require('open-browser-webpack-plugin'),uglifyJSPlugin = require('uglifyjs-webpack-plugin'); const AotPlugin = require('@ngtools/webpack').AngularCompilerPlugin; //import {AngularCompilerPlugin} from '@ngtools/webpack'; //Note : in package.json the last variable (dev) is the param delivered to this function { env: 'dev' }. module.exports = function (env) { console.log('env configuration',env.env); /** * configPerTarget is merged with build.config.json based on the env passed * currently no configuration properties,this configPerTarget not in use per se,keeping just in case - Ogden 4-12-2018 */ var configPerTarget = { localhost: { },development: { },test: { },staging: { },production: { },maintenance: { } }; // Note : '__dirname' is the root file path. const ROOT_DIR = path.resolve(__dirname); const DIST_DIR = path.join(ROOT_DIR,config.dist); // If no env make it dev if (!env) { env = {}; env.env = config.envDevelopment; } //merge config with env specific configPerTarget config = merge(config,configPerTarget[env.env]); // this takes path variables from build.config.json and builds it with given env var appConfigPath = config.envs + config.appConfig.replace('{env}',env.env); var webPackConfig = { entry: ['babel-polyfill',config.src + config.entry],//main.ts output: { path: path.resolve(__dirname,config.dist),filename: config.buildjs,sourceMapFilename: config.buildjsmap,chunkFilename: '[id].[hash:6].chunk.js' },module: { rules: [ { test: /.html$/,use: 'raw-loader' },{ test: /.css$/,{ test: /.ts$/,loaders: [ 'ts-loader','angular2-template-loader','angular-router-loader'] },{ test: /.scss$/,exclude: /node_modules/,loaders: ['style-loader','css-loader','sass-loader'],},//For images. { test: /.(jpe?g|png|gif|svg)$/i,loader: 'file-loader?name=app/assets/images/[name].[ext]' },{ test: /.(ttf|eot|woff|woff2)$/,loader: 'file-loader' },] },//https://webpack.js.org/configuration/devtool/ //Webpack 4.4 has its own mode development and production,which are environment modes //do Webpack 4.4 is handling the devtool sourcemap config where in the past it was not //looks like we no longer have to worry about setting devtool //https://github.com/damianobarbati/yarsk/blob/50b6f352a13ec2e778fa8b252f915550b6132964/config/webpack.config.js#L110 //devtool: config.devtool,resolve: { modules: [__dirname + path.sep + 'src',__dirname,'node_modules'],extensions: ['.js','.ts','.scss','.css'] },plugins: [ new htmlPlugin({ template: config.src + config.index }),new revPlugin({ cwd: config.src,files: '**/*.html',outputPageName: function (filename) { return filename; },modifyReved: function (filename) { return filename.replace(/(/style/|/script/)/,'') } }),//Makes AppConfig variable available in the application code. new extendedDefinePlugin({ AppConfig: require(appConfigPath) }),//Usefull if you need remove some files or folders before compilation processes. //currently not used (no dist file). new webpackDelPlugin({ match: path.join(DIST_DIR,'*.*') }),//opens browser after compilation. new openBrowserPlugin({ url: 'http://localhost:8080' }) ] } //********************************AOT Compilation*************************************** */ //-- AOT Compilation from this point on,currently AOT runs in all environments //this seems helpful because you get to see AOT build errors before pushing to build server //the downside might be more mangled code and harder to debug source code... if (env.env === config.envLocalhost) return webPackConfig; webPackConfig.module.rules.push( { test: /.ts$/,loaders: ['@ngtools/webpack'] } ); webPackConfig.plugins.push(new AotPlugin({ tsConfigPath: './tsconfig-aot.json',//mainPath: path.resolve('./src/main.ts'),entryModule: path.join(config.src,'app/app.module#AppModule') })); webPackConfig.optimization = { minimizer: [ new uglifyJSPlugin({ uglifyOptions: { output: { comments: false,ascii_only: true } } }) ] } return webPackConfig; } 的package.json { "name": "tsl-frontend","version": "0.1.0","scripts": { "test": "karma start","build-localhost": "webpack --mode development --progress --colors --env.env localhost","build-development": "webpack --mode development --progress --colors --env.env development","build-staging": "webpack --mode production --progress --colors --env.env staging","build-production": "webpack --mode production -p --progress --colors --env.env production","build-maintenance": "webpack --mode production -p --progress --colors --env.env maintenance","serve": "webpack-dev-server --mode development --inline --progress --colors --env.env development","serve-production": "webpack-dev-server --mode production --inline --progress --colors --env.env development","serve-localhost": "webpack-dev-server --mode development --inline --progress --colors --env.env localhost","serve-host": "webpack-dev-server --host 0.0.0.0 --port 80 --disable-host-check --mode development --inline --progress --colors --env.env localhost","serve-maintenance": "webpack-dev-server --mode development --inline --progress --colors --env.env maintenance" },"dependencies": { "@angular/animations": "^5.2.11","@angular/cdk": "^2.0.0-beta.12","@angular/common": "^5.2.11","@angular/compiler": "^5.2.11","@angular/compiler-cli": "^5.2.11","@angular/core": "^5.2.11","@angular/forms": "^5.2.11","@angular/http": "^5.2.11","@angular/material": "^2.0.0-beta.12","@angular/platform-browser": "^5.2.11","@angular/platform-browser-dynamic": "^5.2.11","@angular/platform-server": "^5.2.11","@angular/router": "^5.2.11","@ng-bootstrap/ng-bootstrap": "^1.1.2","@types/file-saver": "^1.3.0","angular2-jwt": "^0.2.3","angular2-text-mask": "^8.0.5","bootstrap": "^4.1.2","chart.js": "^2.7.2","file-saver": "^1.3.8","font-awesome": "^4.7.0","moment": "2.18.1","moment-timezone": "0.5.13","ng2-bootstrap-modal": "1.0.1","ng2-charts": "^1.6.0","ng2-drag-drop": "^2.9.2","ng2-page-scroll": "^4.0.0-beta.12","ng2-toastr": "^4.1.2","popper.js": "^1.14.3","reflect-metadata": "0.1.8","rxjs": "5.5.5","systemjs": "0.19.40","typescript": "^2.9.2","xlsx": "^0.11.19","zone.js": "^0.8.26" },"devDependencies": { "@ngtools/webpack": "^6.0.8","@servicestack/client": "^1.0.14","@types/jasmine": "^2.8.8","@types/node": "7.0.7","angular-router-loader": "^0.6.0","angular2-router-loader": "^0.3.5","angular2-template-loader": "^0.6.2","babel-polyfill": "^6.26.0","css-loader": "^0.28.11","extended-define-webpack-plugin": "^0.1.3","extract-text-webpack-plugin": "^3.0.2","file-loader": "^1.1.11","html-webpack-plugin": "^4.0.0-alpha","jasmine": "^2.99.0","karma": "^1.7.0","karma-sourcemap-loader": "^0.3.7","karma-webpack": "^2.0.13","ng-intercom": "^1.0.0-beta.5-2","ng2-tree": "^2.0.0-rc.11","node-sass": "^4.9.2","open-browser-webpack-plugin": "0.0.5","path": "^0.12.7","raw-loader": "^0.5.1","sass-loader": "^6.0.7","style-loader": "^0.13.2","text-mask-addons": "^3.7.2","toposort": "^1.0.7","ts-loader": "^4.4.2","webpack": "^4.16.1","webpack-cli": "^2.1.5","webpack-del-plugin": "0.0.1","webpack-dev-server": "^3.1.4","webpack-merge": "^4.1.3","webpack-rev-replace-plugin": "^0.1.1" } } tsconfig-aot.json(文件数组包含延迟加载的模块路径) { "compilerOptions": { "target": "es5",//most browsers currently understand this version of Javascript "experimentalDecorators": true,//Angular2 uses Component,Injectable etc "emitDecoratorMetadata": true,//Required for Angular2 to use the metadata in our components //"sourceMap": true "types": [ "node","jasmine" ],// "typeRoots": [ // "node_modules/@types" // ],"lib": [ "es2015","es2015.iterable","dom" ] },"exclude": [ "node_modules" ],"files": [ "src/app/app.module.ts","src/main.ts","src/app.d.ts","src/app/sandbox/sandbox.module.ts","src/app/supplier-xchange/supplier-xchange.module.ts","src/app/company-profile/company-profile.module.ts","src/app/bom/bom.module.ts","src/app/custom-price-column/custom-price-column.module.ts","src/app/neca/neca.module.ts" ],"angularCompilerOptions": { "genDir": "aot",// Specify where Angular can create temporary AOT files "skipMetadataEmit": true // Don't generate not necessary metadata files. They are useful only if you're publishing an Angular UI library } } 这是我的NGINX配置: daemon off; user nginx; worker_processes 2; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; use epoll; accept_mutex off; } http { include /etc/nginx/mime.types; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; #tcp_nopush on; keepalive_timeout 65; client_max_body_size 300m; client_body_buffer_size 300k; large_client_header_buffers 8 64k; gzip on; gzip_http_version 1.0; gzip_comp_level 6; gzip_min_length 0; gzip_buffers 16 8k; gzip_proxied any; gzip_types text/plain text/css text/xml text/javascript application/xml application/xml+rss application/javascript application/json; gzip_disable "MSIE [1-6]."; gzip_vary on; include /etc/nginx/conf.d/*.conf; } server { listen 80 default_server; listen [::]:80 default_server; server_name _; # API Server # location /api/ { # proxy_pass ${MY_API_URL}/; # } # Main location / { set $cors "true"; if ($http_origin ~* (http://d.mywebsite.comS*)$) { set $cors "true"; } if ($request_method = 'OPTIONS') { set $cors "${cors}options"; } if ($request_method = 'GET') { set $cors "${cors}get"; } if ($request_method = 'POST') { set $cors "${cors}post"; } if ($cors = "trueget") { add_header 'Access-Control-Allow-Origin' "$http_origin"; add_header 'Access-Control-Allow-Credentials' 'true'; } if ($cors = "truepost") { add_header 'Access-Control-Allow-Origin' "$http_origin"; add_header 'Access-Control-Allow-Credentials' 'true'; } if ($cors = "trueoptions") { add_header 'Access-Control-Allow-Origin' "$http_origin"; add_header 'Access-Control-Allow-Credentials' 'true'; add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS'; add_header 'Access-Control-Allow-Headers' 'Authorization,Content-Type,Accept,Origin,User-Agent,DNT,Cache-Control,X-Mx-ReqToken,Keep-Alive,X-Requested-With,If-Modified-Since'; add_header 'Content-Length' 0; add_header 'Content-Type' 'text/plain charset=UTF-8'; return 204; } root /usr/share/nginx/html; index index.html index.htm; try_files $uri$args $uri$args/ /index.html; } #error_page 404 /404.html; # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } } 认为这些文件对这个问题很重要,但以防万一: main.ts //CSS STYLES import './styles'; import 'reflect-metadata'; //Zone JS is required by Angular itself. import 'zone.js/dist/zone'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { AppModule } from './app/app.module'; import { enableProdMode } from '@angular/core'; //remaining in ProdMode even in dev because of ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked errors //http://www.allenhashkey.com/web-development/angular2/angular-2-expression-changed-after-it-has-been-checked-exception/ enableProdMode(); // if (!AppConfig.isDevelopment) { // enableProdMode(); // } platformBrowserDynamic().bootstrapModule(AppModule) .then(success => console.log('Bootstrap success')) .catch(err => console.error("Bootstrap module failure: ",err)); app.module.ts // Vendor import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { LocationStrategy,HashLocationStrategy } from '@angular/common'; import { Injector } from '@angular/core'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { Ng2DragDropModule } from 'ng2-drag-drop'; import { ToastModule } from 'ng2-toastr/ng2-toastr'; import { Ng2PageScrollModule } from 'ng2-page-scroll'; // Routing import { AppRoutingModule,routableComponents } from './app-routing.module'; //Components import { AppComponent } from './app.component'; //Shared Module import { SharedModule } from './@shared/shared.module'; //Feature Modules import { CoreModule } from './@core/core.module'; import { DashboardModule } from './dashboard/dashboard.module'; import { ProductModule } from './product/product.module'; import { SearchModule } from './search/search.module'; import { LoginModule } from './login/login.module'; import { ExampleModule } from './example/example.module'; import { ProfileModule } from './profile/profile.module'; import { ResetPasswordModule } from './reset-password/reset-password.module'; import { EdataFlexModule } from './e-data-flex/e-data-flex.module'; import { SubmittalManagerModule } from './submittal-manager/submittal-manager.module'; import { PimModule } from './pim/pim.module'; import { AnalyticsModule } from './analytics/analytics.module'; import { InviteUserModule } from './invite-user/invite-user.module'; import { DownloadsModule } from './downloads/downloads.module'; import { SettingsModule } from './settings/settings.module'; import { ChangeBulletinModule } from './change-bulletin/change-bulletin.module'; //Singletons - A Singleton Service shall only be kept in app.module.ts "providers" (array) //and it shall not be placed in any other component or service provider (array). import { TokenService } from './@core/auth/token.service'; // Intercom Module import { IntercomModule } from 'ng-intercom'; import { BootstrapModalModule } from 'ng2-bootstrap-modal'; @NgModule({ imports: [ SharedModule,BrowserModule,DashboardModule,ProductModule,SearchModule,ProfileModule,ExampleModule,LoginModule,CoreModule,ResetPasswordModule,EdataFlexModule,SubmittalManagerModule,PimModule,AnalyticsModule,InviteUserModule,DownloadsModule,SettingsModule,ChangeBulletinModule,//Do not import feature modules below "AppRoutingModule" AppRoutingModule,BrowserAnimationsModule,BootstrapModalModule.forRoot({container:document.body}),Ng2PageScrollModule.forRoot(),Ng2DragDropModule.forRoot(),ToastModule.forRoot(),IntercomModule.forRoot({ appId:AppConfig.intercom["appId"],// TSO App Id updateOnRouterChange : true // will automatically run 'update' on router event changes. }) ],declarations: [ AppComponent,routableComponents ],providers: [ { provide: LocationStrategy,useClass: HashLocationStrategy },TokenService ],bootstrap: [AppComponent] }) export class AppModule { /** * Allows for retrieving singletons using `AppModule.injector.get(MyService)` * This is good to prevent injecting the service as constructor parameter. */ static injector: Injector; constructor(injector: Injector) { AppModule.injector = injector; } } 解决方法
这是因为当你使用AOT时,代码会被一些有趣的UTF-8符号所证实; in在i0.?crt中你的情况
你需要告诉nginx使用UTF-8字符集 server { listen 80 default_server; listen [::]:80 default_server; server_name _; charset UTF-8; #<==== Add this (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |