从NGINX提供服务时,带有AOT的延迟加载模块-TypeError:''不起作用 [英] Lazy Loaded Modules with AOT - TypeError: '' is not a function when served from NGINX
问题描述
这是我的dist文件,可以自我复制:
-
而这在Chrome浏览器中:
ERROR TypeError:i0.ɵcrt不是函数
要详细了解Chrome中的错误,这是源地图行错误的代码集:
我看到var
的创建i0
是这一行:var i0 = __webpack_require __(/ *! @ angular / core * / ./node_modules/@angular/core/esm5/core.js);
在我的开发服务器上,使用父级文件夹和我的dist文件夹的node_modules:
< a href = https://i.stack.imgur.com/jeFWs.png rel = nofollow noreferrer>
我在开发服务器上的文件:
这里是从本地主机提供的资源文件的比较:
这是开发服务器提供的资源文件:
好,所以这里是我的配置和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;
//从 @ ngtools / webpack导入{AngularCompilerPlugin};
//注意:在package.json中,最后一个变量(dev)是传递给此函数的参数{env:‘dev’}。
module.exports = function(env){
console.log( env configuration,env.env);
/ **
* configPerTarget与基于传递的env的build.config.json合并
*当前没有配置属性,该configPerTarget本身未使用,以防万一-Ogden 2018年4月12日
* /
var configPerTarget = {
本地主机:{
},
开发:{
},
测试:{
},
阶段:{
},
生产:{
},
维护:{
}
};
//注意: __ dirname是根文件路径。
const ROOT_DIR = path.resolve(__ dirname);
const DIST_DIR = path.join(ROOT_DIR,config.dist);
//如果没有环境,则将其设为dev
if(!env){
env = {};
env.env = config.env开发;
}
//与特定于env的配置合并configPerTarget
config = merge(config,configPerTarget [env.env]);
//从build.config.json中获取路径变量,并使用给定的env构建它。
var appConfigPath = config.envs + config.appConfig.replace('{env}',env .env);
var webPackConfig = {
entry:['babel-polyfill',config.src + config.entry],// main.ts
输出:{
路径:path.resolve(__ dirname,config.dist),
文件名:config.buildjs,
sourceMapFilename:config.buildjsmap,
chunkFilename:'[id]。[hash :6] .chunk.js'
},
模块:{
规则:[
{测试:/\.html$/,使用:'raw-loader' },
{测试:/\.css$/,使用:'raw-loader'},
{
测试:/\.ts$/,
载入器:[[
'ts-loader',
'angular2-template-loader',
'angular-router-loader']
},
{
测试:/\.scss $ /,
排除:/ node_modules /,
载入程序:['style-loader','css-loade r’, sass-loader],
},
//用于图片。
{test:/\.(jpe?g|png|gif|svg)$/i,加载程序: file-loader?name = app / assets / images / [name]。[ext]'}} ,
{
测试:/\.(ttf|eot|woff|woff2)$/,
loader:'file-loader'
},
]
},
//https://webpack.js.org/configuration/devtool/
// Webpack 4.4具有自己的模式开发和生产模式,即环境模式
// do Webpack 4.4正在处理devtool sourcemap配置,在过去它不是
//看起来我们不再需要担心设置devtool
//https://github.com/damianobarbati /yarsk/blob/50b6f352a13ec2e778fa8b252f915550b6132964/config/webpack.config.js#L110
// devtool:config.devtool,
解析:{
模块:[__dirname + path.sep +'src ',__ dirname,'node_modules'],
扩展名:['.js','。ts','。scss','。css']
},
插件:[
个新的htmlPlugin({
模板:config.src + config.index
}),
个新的revPlugin({
cwd:config。 src,
文件:'** / *。html',
outputPageName:函数(文件名){
返回文件名;
},
ModifyReved:函数(文件名){
返回filename.replace(/(\ / style\ / | \ / script\ /)/,'')
}
}),
//在应用程序代码中使AppConfig变量可用。
新的extendedDefinePlugin({
AppConfig:require(appConfigPath)
}),
//如果在编译过程之前需要删除一些文件或文件夹,请使用full。
//当前未使用(无dist文件)。
new webpackDelPlugin({match:path.join(DIST_DIR,'*。*')}),
//在编译后打开浏览器。
新的openBrowserPlugin({url:'http:// localhost:8080'})
]
}
// ********* *********************** AOT编译************************* ************** * /
//-从现在开始进行AOT编译,当前AOT在所有环境中运行
//这似乎很有用,因为您可以在尝试构建服务器
之前先查看AOT生成错误//缺点可能是代码混乱,更难调试源代码...
if(env.env === config.envLocalhost )返回webPackConfig;
webPackConfig.module.rules.push(
{测试:/\.ts$/,装载程序:[’@ 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 = {
最小化器:[
new uglifyJSPlugin({
uglifyOptions:{
输出:{
注释:false,
ascii_only:true
}
}
})
]
}
return webPackConfig;
}
package.json
{
name: tsl-frontend,
version: 0.1.0,
脚本:{
test:业力开始,
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暂存,
构建-生产: webpack --mode生产-p --progress --colors --env.env生产,
构建-维护 : webpack --mode生产-p --progress --colors --env.env维护,
serve: webpack-dev-server --mode development --inline --progress --colors --env.env开发,
serve-production: webpack-dev-server --mode生产--inline --progress --colors --env.env开发,
serve-localhost: webpack-dev-server --mode develo pment --inline --progress --colors --env.env localhost,
serve-host: webpack-dev-server --host 0.0.0.0 --port 80 --disable-host-检查--mode development --inline --progress --colors --env.env localhost,
serve-maintenance: webpack-dev-server --mode development --inline --progress-颜色--env.env维护
},
依赖关系:{
@ 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,
@type s / 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 / file-saver: ^ 1.3.0,
@ types / jasmine: ^ 2.8.8,
@ types / node: 7.0。 7,
angular-router-loader: ^ 0.6.0,
angula r2-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,
file-saver: ^ 1.3.8,
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,//大多数浏览器当前了解此版本的Javascript
experimentalDecorators:true,// Angular2使用Component,Injectable等
embedDecoratorMetadata:true,// Angular2在组件中使用元数据是必需的
// sourceMap:true
types:[
node,
茉莉花
],
// typeRoots:[
// node_modules / @ types
//],
lib:[
es2015,
es2015.iterable,
dom
]
},
exclude:[
n ode_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,//指定Angular在何处可以创建临时AOT文件
skipMetadataEmit:true //不生成不必要的元数据文件。仅当您发布Angular UI库
}
}
<时,它们才有用p>这是我的NGINX配置:daemon off;
个用户nginx;
worker_processes 2;
error_log /var/log/nginx/error.log警告;
pid /var/run/nginx.pid;
个事件{
worker_connections 1024;
个使用epoll;
accept_mutex关闭;
}
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应用程序/八位字节流;
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;
发送文件;
#tcp_nopush on;
keepalive_timeout 65;
client_max_body_size 300m;
client_body_buffer_size 300k;
large_client_header_buffers 8 64k;
gzip压缩;
gzip_http_version 1.0;
gzip_comp_level 6;
gzip_min_length 0;
gzip_buffers 16 8k;
gzip_proxied任何;
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;
包括/etc/nginx/conf.d/*.conf;
}
服务器{
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
#API服务器
#位置/ api / {
#proxy_pass $ {MY_API_URL} /;
#}
#主要
位置/ {
set $ cors true;
if($ http_origin〜*(http:\ / \ / d\.mywebsite\.com\S *)$){
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访问控制允许凭据 true;
}
if($ cors = truepost){
add_header'Access-Control-Allow-Origin' $ http_origin;
add_header访问控制允许凭据 true;
}
if($ cors = trueoptions){
add_header'Access-Control-Allow-Origin' $ http_origin;
add_header访问控制允许凭据 true;
add_header'访问控制允许方法''GET,POST,选项';
add_header'访问控制允许标题''授权,内容类型,接受,来源,用户代理,DNT,缓存控制,X-Mx-ReqToken,保持活动,X-请求,If-Modified-Since';
add_header内容长度 0;
add_header内容类型 text / plain charset = UTF-8;
返回204;
}
root / usr / share / nginx / html;
index index.html index.htm;
try_files $ uri $ args $ uri $ args / /index.html;
}
#error_page 404 /404.html;
#将服务器错误页面重定向到静态页面/50x.html
#
error_page 500502503504 / 50x.html;
location = /50x.html {
root / usr / share / nginx / html;
}
}
不要以为这些文件对这个问题很重要,但是情况:
main.ts
// CSS样式
import'./styles';
导入反射元数据;
// Zone JS是Angular本身需要的。
导入 zone.js / dist / zone;来自 @ angular / platform-browser-dynamic的
import {platformBrowserDynamic};
从 ./app/app.module导入{AppModule};
从 @ angular / core导入{enableProdMode};
//由于ExpressionChangedAfterItHaHasBeenCheckedError,即使在开发人员中也保留在ProdMode中:表达式在检查错误后已更改
//http://www.allenhashkey.com/web- development / angular2 / angular-2-expression-changed-it-before-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
//供应商
从'@ angular / core'导入{NgModule};来自 @ angular / platform-browser的
import {BrowserModule};来自 @ angular / common的
import {LocationStrategy,HashLocationStrategy};从 @ angular / core导入
{注入器};来自 @ angular / platform-browser / animations的
import {BrowserAnimationsModule};从 ng2-drag-drop中导入
{{Ng2DragDropModule};
从ng2-toastr / ng2-toastr导入{ToastModule};
从 ng2-page-scroll导入{Ng2PageScrollModule};
//路由
import {AppRoutingModule,routableComponents}来自 ./app-routing.module;
//组件
从‘./app.component’中导入{AppComponent};
//共享模块
从‘./@shared/shared.module’导入{SharedModule};
//功能模块
从‘./@core/core.module’中导入{CoreModule};
从 ./dashboard/dashboard.module导入{DashboardModule};
从 ./product/product.module导入{ProductModule};
从 ./search/search.module导入{SearchModule};
从 ./login/login.module导入{LoginModule};
从 ./example/example.module导入{ExampleModule};
从 ./profile/profile.module导入{ProfileModule};
从 ./reset-password/reset-password.module导入{ResetPasswordModule};
从 ./e-data-flex/e-data-flex.module导入{EdataFlexModule};
从 ./submittal-manager/submittal-manager.module中导入{SubmittalManagerModule};
从 ./pim/pim.module导入{PimModule};
从 ./analytics/analytics.module导入{AnalyticsModule};
从 ./invite-user/invite-user.module导入{InviteUserModule};
import {DownloadsModule} from’./downloads/downloads.module’;
从 ./settings/settings.module导入{SettingsModule};
从 ./change-bulletin/change-bulletin.module导入{ChangeBulletinModule};
// Singletons-单例服务仅应保存在app.module.ts提供者(数组)中
//不得将其放置在任何其他组件或服务提供者(数组)中。
从 ./@core/auth/token.service导入{TokenService};
//对讲模块
从ng-intercom导入{IntercomModule};
从 ng2-bootstrap-modal导入{BootstrapModalModule};
@NgModule({
进口:[
SharedModule,
BrowserModule,
DashboardModule,
ProductModule,
SearchModule,
ProfileModule,
ExampleModule,
LoginModule,
CoreModule,
ResetPasswordModule,
EdataFlexModule,
SubmittalManagerModule,
PimModule,
AnalyticsModule,
InviteUserModule,
DownloadsModule,
SettingsModule,
ChangeBulletinModule,
//不要在 AppRoutingModule以下导入功能模块
AppRoutingModule,
BrowserAnimationsModule,
BootstrapModalModule.forRoot({container:document.body}),
Ng2PageScrollModule.forRoot(),
Ng2DragDropModule.forRoot(),
ToastModule.forRoot() ,
IntercomModule.forRoot({
appId:AppConfig.intercom [ appId],// TSO应用ID
updateOnRouterChange:true //将在路由器事件更改时自动运行更新。
})
],
声明:[
AppComponent,
routableComponents
],
提供者:[
{提供:LocationStrategy,useClass: HashLocationStrategy},
TokenService
],
引导程序:[AppComponent]
})
导出类AppModule {
/ **
*允许使用AppModule.injector.get(MyService)`获取单例。
*这样可以防止将服务作为构造函数参数注入。
* /
静态进样器:进样器;
构造函数(注入器:Injector){
AppModule.injector =注入器;
}
}
解决方案因为当您使用AOT时,代码会被一些有趣的UTF-8符号丑化;
ɵ
在i0中。ɵcrt
在您的情况下
您需要告诉Nginx使用UTF-8字符集
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
字符集UTF-8; #< ====添加此
Here are my dist files to reproduce yourself:
The breakdown:
- My dist build, with AOT and Lazy Loaded modules works fine when served with npm packages webpack-dev-server or live-server
- It is only when I copy dist to NGINX html directory and NGINX serves the files that I see Javascript errors in Firefox and Chrome
- I have tried many different webpack configurations.
- I am not importing my Lazy Loaded modules in any Typescript file
- With AOT compilation OFF my app and Lazy Modules serve fine from NGINX
- The TypeError: '' is not a function error is coming from Lazy Loaded Modules being served with NGINX
I am using the official Angular package
@ngtools/webpack
to add AOT compilation to my Angular 5 app. This article explains how to use@ngtools/webpack
to add AOT to a Webpack build project. Very simple, though the article does not mention the needed step to add the Lazy Load module file paths totsconfig-aot.json
. AOT fails with out that step.All works great localhost with:
npm run serve
My
npm run serve
command is an in memory compilation and the resources are served localhost from memory using the npm packagewebpack-dev-server
.When I deploy to my development server, the compilation files are stored on disk and my dev server serves the resources with
NGINX
.I have lazy loaded modules that, when loaded are throwing strange errors like this in Firefox:
TypeError: i0.\u0275crt is not a function
And this in Chrome:
ERROR TypeError: i0.ɵcrt is not a function
Going to more detail with the error in Chrome, here is the source maps line of code throwing the error:
I see that the creation of var
i0
is this line:var i0 = __webpack_require__(/*! @angular/core */ "./node_modules/@angular/core/esm5/core.js");
On my dev server, node_modules as at the parent level with my dist folder:
My files on my dev server:
Here is a comparison of the resource files served up from localhost:
And here is the resource files served up from the development server:
OK so here comes my configuration and npm package versions:
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$/, use: 'raw-loader' }, { 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/file-saver": "^1.3.0", "@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", "file-saver": "^1.3.8", "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 (files array includes lazy loaded module paths)
{ "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 } }
And here is my NGINX configuration:
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\.com\S*)$) { 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; } }
Do think these files matter to this problem but just in case:
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; } }
解决方案It's because when you use AOT, the code is uglified with some funny UTF-8 symbols;
ɵ
ini0.ɵcrt
in your caseYou need to tell nginx to use UTF-8 charset
server { listen 80 default_server; listen [::]:80 default_server; server_name _; charset UTF-8; #<==== Add this
这篇关于从NGINX提供服务时,带有AOT的延迟加载模块-TypeError:''不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!