primefaces/primeng

AOT support

ammar91 opened this issue · 40 comments

I'm trying to compile my application with AOT compiler but getting an error with Primeng modules.

Error: Unexpected value 'ContextMenuModule' exported by the module 'SharedModule'

My App SharedModuleexport primeng modules that my app require including

import { ContextMenuModule } from 'primeng/components/contextmenu/contextmenu';
import { DataTableModule } from 'primeng/components/datatable/datatable';
import { DialogModule } from 'primeng/components/dialog/dialog';
import { SplitButtonModule } from 'primeng/components/splitbutton/splitbutton';
import { TabViewModule } from 'primeng/components/tabview/tabview';
import { TooltipModule } from 'primeng/components/tooltip/tooltip';

Any thoughts?

@ammar91 is this happening with the beta 15?

@ammar91 we haven't taken the plunge in AOT yet so I can't really help, sorry. Maybe @cagataycivici can give some I insight?

@cagataycivici Could you please put your thoughts on this?

Seems to have to do with not having a metadata.json file.
valor-software/ngx-bootstrap#933

Probably just have to wait until they have time to do this.

Now that the Angular 2 officially released. It would be good to have it working in the next release.

Any chance of having it functional in beta 16?

Will this be available in the next beta, or later?

@qdouble How does material 2 and other 3rd party packages run fine in AOT mode? I'm even able to compile my application in AOT mode if I remove PNG dependency, isn't that mean PNG not AOT compatible yet?

@ammar91 I'm not sure of every step 3rd party developers have to take...the main problem may be that a lot of these libraries were created before AOT was even a consideration and need to be updated.

As far as the png thing, link to a reproduction of it over on my repo and I can look at it, may need a loader or something else, I haven't dealt with that yet

According to this github issue angular/angular#11889 , it looks like the 3rd party module must ship the metadata files.

We haven't managed to spare time to look into this yet, we'd appreciate feedback on how to add AOT compatibility.

The problem is also mentioned in this issue angular/angular#11262

Thanks we'll review after beta17.

@cagataycivici I made a pull request. Please check #1004
It would be great to have it in beta17.

AOT support work has started and we definitely need feedback. As far as I understand metadata files are only required for non-ts files, from the docs;

The "skipMetadataEmit" : true property prevents the compiler from generating metadata files with the compiled application. Metadata files are not necessary when targeting TypeScript files, so there is no reason to include them.

@ammar91's PR adds metadata files which we'd like to avoid maintaining, my initial idea is make sure sure ngc properly compiles our ts files and also ship the ts files in the npm package because until now we only ship js. When the ts files of PrimeNG will be in npm and as a result in your app's node_modules, I'm hoping you will be able to compile your app with AOT without need for metadata files. Of course, we'll make sure ngc compiles our ts without issues before releasing.

Feedback is welcome.

@cagataycivici I agree, metadata.json should not be under version control. I believe you could generate those before publishing to npm. This is how ng-bootstrap and angular material doing as well.

Also, AMO shipping the ts files in npm package would not be an ideal solution.

My current decision is not to include ts and generate metadata.json files when publishing. I'd appreciate if you could point me to the process of generating these files.

@cagataycivici Sure, These are the steps for generating the files

  1. Install angular compiler

npm install @angular/compiler-cli @angular/platform-server --save

  1. Get tsconfig for AOT from the Angular doc
    https://angular.io/docs/ts/latest/cookbook/aot-compiler.html

  2. Add script in package.json

"scripts": {
    "ngc": "ngc -p ./tsconfig-aot.json"
  }
  1. Changed the components template url (if they are not inline) from Absolute to Relative Path.

Eg:

@Component({
    templateUrl: 'components/blockui/blockui.html'
})

To

@Component({
    templateUrl: './blockui.html'
})
  1. Remove typings.json in favor of typescript 2.0, new way of defining type declaration files.
    https://blogs.msdn.microsoft.com/typescript/2016/06/15/the-future-of-declaration-files/

And add these in tsconfig so it looks for the typings file in the correct location

 "typeRoots": [
            "node_modules/@types"
        ],
  "types": [
            "node",
            "jquery",
            "fullcalendar"
        ]

You may notice core-js is not listed, that is because it may throw duplicate identifier error if you include in list.

  1. Now finally run

npm run ngc

You may get several errors which are mostly related to access modifiers mentioned in the below article (3rd point, that says private, protected accessors should be changed to public for any members accessed from template)

https://medium.com/@isaacplmann/making-your-angular-2-library-statically-analyzable-for-aot-e1c6f3ebedd5#.9wzvvaym0

After fixing those, you should be able to successfully compile with ngc.

Hope that helps!

Thanks, I'll work on this soon.

Work has started, I'm doing an entire code review to remove "any" types and check aot compatibility. As a side note, I had to add "skipMetadataEmit" : false to get the metadata json files also somehow haven't done some steps like number 5 but it worked fine.

Quick question, does setting "noImplicitAny" in tsconfig-aot.json as false have any impact on AOT metadata json files or ngFactory? Right now there are aot compilation issues due to usage of protected-private variables in inline templates of components as expected, my main focus is on that to get AOT ready instead of replacing "any" with actual type which can be done with a refactor later.

Alright, I've done the changes for AOT support.

@cagataycivici That's Great, There should be no impact by setting "noImplicitAny" to false.
Looking forward to try this out. Thanks so much..

hello @cagataycivici

You said on this post that primeng is ready for aot.

Nevertheless, I cannot compile even with a simple import (not using any component on html) using the follow primeng version:
"primeng": "^2.0.2",

module
`import { CheckboxModule } from 'primeng/primeng';

@NgModule({
imports: [ CommonModule, FormsModule, CheckboxModule ],
declarations: [ LoginComponent ],
exports: [ LoginComponent ]
})`

component
import { CheckboxModule } from 'primeng/primeng';

tsconfig-aot.json
{
"compilerOptions": {
"baseUrl": ".",
"declaration": true,
"stripInternal": true,
"experimentalDecorators": true,
"strictNullChecks": false,
"noImplicitAny": false,
"module": "es2015",
"moduleResolution": "node",
"paths": {
"@angular/core": ["node_modules/@angular/core"],
"rxjs/": ["node_modules/rxjs/"]
},
"rootDir": ".",
"outDir": "dist",
"sourceMap": true,
"inlineSources": true,
"target": "es5",
"skipLibCheck": true,
"lib": [
"es2015",
"dom"
]
},
"files": [
"index.ts"
],
"angularCompilerOptions": {
"strictMetadataEmit": true
}
}
rollup-config.json
`import rollup from 'rollup'
import nodeResolve from 'rollup-plugin-node-resolve'
import commonjs from 'rollup-plugin-commonjs';
import uglify from 'rollup-plugin-uglify'

export default {
entry: 'dist/index.js',
dest: 'dist/bundles/xplainsnippets.umd.js', // output a single application bundle
sourceMap: false,
format: 'umd',
moduleName: 'XplainSnippets',
globals: {
'@angular/core': 'ng.core',
'rxjs/Observable': 'Rx',
'rxjs/ReplaySubject': 'Rx',
'rxjs/add/operator/map': 'Rx.Observable.prototype',
'rxjs/add/operator/mergeMap': 'Rx.Observable.prototype',
'rxjs/add/observable/fromEvent': 'Rx.Observable',
'rxjs/add/observable/of': 'Rx.Observable'
},
onwarn: function(warning) {
// Skip certain warnings

// should intercept ... but doesn't in some rollup versions
if ( warning.code === 'THIS_IS_UNDEFINED' ) { return; }
// intercepts in some rollup versions
if ( warning.indexOf("The 'this' keyword is equivalent to 'undefined'") > -1 ) { return; }

// console.warn everything else
console.warn( warning.message );

},
plugins: [
nodeResolve({jsnext: true, module: true}),
commonjs({
include: 'node_modules/rxjs/**',
}),
uglify()
]
}`

When running: ngc -p tsconfig-aot.json && rollup -c rollup-config.js

The terminal throws:
` ngc -p tsconfig-aot.json && rollup -c rollup-config.js

⚠️ 'default' is imported from external module 'rollup' but never used

� 'CheckboxModule' is not exported by node_modules\primeng\primeng.js
https://github.com/rollup/rollup/wiki/Troubleshooting#name-is-not-exported-by-module
dist\src\app\login\login.module.js (5:9)
3: import { FormsModule } from '@angular/forms';
4: import { LoginComponent } from './login.component';
5: import { CheckboxModule } from 'primeng/primeng';`

When I check the primeng folder on my node_module. I see that there are no .metadata.json info overthere. These files in source libraries is needed for aot. Could you include them on your release?

The follow links could be useful in order to find the solution:
http://www.usefuldev.com/blog/post/using-ngc-to-build-an-angular-2-library-project
https://angular.io/docs/ts/latest/cookbook/aot-compiler.html

Thank you in advance.

Hi @cagataycivici I am facing the same issue as @Pilukina, is aot in 2.0 branch? By the way PrimeNg is fantastic!

@Pilukina @edwinquaihoi
change import { CheckboxModule, DataTableModule, SharedModule, ... } from 'primeng/primeng';
to
import {CheckboxModule} from 'primeng/components/checkbox/checkbox';
import {DataTableModule} from 'primeng/components/datatable/datatable';
import {SharedModule} from 'primeng/components/common/shared';
ect..

Thank you so much for your answer. The bug is solved by primeng, they have included the needed .metadata.json for aot on version 2.0.3.

Nevertheless the components could be imported and compiled using both paths.

I could not success to run rollup (after AOT compilation) my ang2 app with primeNG modules. I am getting the error below for all modules:

'EditorModule' is not exported by 'node_modules\primeng\components\editor\editor.js'

Anyone knows how we can overcome the issue?

I'm using primeng v2.0.3, The node_modules\primeng\components\editor\editor.js exports exports.EditorModule = EditorModule; on line 139.
I have checked the file editor.metadata.json (mandatory for aot compiling) is there.

Could you check which version of primeng are you using and if the metadata.json is included?

Hi Pilukina,

I am simply following the official guidelines for Ang2 AOT. There are 2 steps, 1st is ngc, 2nd is rollup:

https://angular.io/docs/ts/latest/cookbook/aot-compiler.html

I am using 2.0.5, ngc compiles but rollup throws error. Sorry for missleading.

'GrowlModule' is not exported by 'node_modules\primeng\components\growl\growl.js' 'ProgressBarModule' is not exported by 'node_modules\primeng\components\progressbar\progressbar.js' 'SharedModule' is not exported by 'node_modules\primeng\components\common\shared.js' 'EditorModule' is not exported by 'node_modules\primeng\components\editor\editor.js' 'ButtonModule' is not exported by 'node_modules\primeng\components\button\button.js' 'InplaceModule' is not exported by 'node_modules\primeng\components\inplace\inplace.js' 'InputTextModule' is not exported by 'node_modules\primeng\components\inputtext\inputtext.js' 'SpinnerModule' is not exported by 'node_modules\primeng\components\spinner\spinner.js' 'InputMaskModule' is not exported by 'node_modules\primeng\components\inputmask\inputmask.js' 'CalendarModule' is not exported by 'node_modules\primeng\components\calendar\calendar.js' 'ConfirmDialogModule' is not exported by 'node_modules\primeng\components\confirmdialog\confirmdialog.js' 'GrowlModule' is not exported by 'node_modules\primeng\components\growl\growl.js' 'ProgressBarModule' is not exported by 'node_modules\primeng\components\progressbar\progressbar.js' 'ConfirmationService' is not exported by 'node_modules\primeng\components\common\api.js' � 'EditorModule' is not exported by node_modules\primeng\components\editor\editor.js

I'm afraid I can't help you. Nevertheless, I recommend you directly write a new topic on ngprime forum: https://forum.primefaces.org/viewforum.php?f=35
They helped me very soon. Good luck! :)

Actually there is a workaround to specify the named exports in the rollup-config like this:

plugins: [
  commonjs({
    include: 'node_modules/**',
    namedExports: {
      // Add every import you need from primeng to the list
      'node_modules/primeng/primeng.js': ['SharedModule', 'DataTableModule', 'DataTable']
    }
  })
]

Thanks, that solved the problem.

it solves the problem with a work around.

The primeng modules should 'export' stuff properly.

Could this be hot fixed please? PrimeNG is not properly exporting stuff.

jrood commented

@cagataycivici can you please reopen this issue since it seems to still not be fixed?