Trying to NPM publish and install a custom angular2 component with Angular-CLI; only compiles the first time - angularjs

I'm having a most unusual and frustrating problem.
I have an Ng2 component called via-date-picker that I am trying to NPM publish so that it can be easily used in other projects. In order to do so, I have made it into an Angular2 component library. The via-date-picker exports a module called ViaDatePickerModule, which I want to import elsewhere.
In order to test and make sure that it is being published correctly, I am NPM-installing and importing it into an otherwise empty Angular-CLI project that I am calling npm-test.
So I run my npm-test application using "ng serve", and I get this error:
ERROR in ViaDatePickerModule is not an NgModule
webpack: Failed to compile
Yet despite that error, the project compiles anyway:
And when I open up my project, lo and behold, everything works!!
But this only happens the first time that I run the project. On successive attempts to run the project via "ng serve", I get the same compilation error, but this time the project just flat-out refuses to complete it's compilation:
I have no idea why I'm getting this error, and why Angular-CLI will run my project sometimes but not others.
I've scoured the web for answers and tried every solution I can find for this error, as well as every other thing I can think of:
I've tried adjusting the tsConfig settings in my component library
I've tried using rollup.js instead of gulp.js to build my component library
I've tried copying existing, working component libraries, then carefully swapping out the existing code for my own
I've downgraded Angular CLI
I've upgraded Angular CLI
I've downgrade Typescript
I've upgraded Typescript
I've deleted and re-installed node_modules several times
I've deleted and re-started my whole project twice
No matter what I do, I keep coming to the same webpack error that I posted above; that ViaDatePickerModule is not an NgModule. I'm completely out of ideas. Any help that anyone could provide would be crazy helpful.
For the sake of complete thoroughness, I've created a public repo on github here containing all the files involves, divided into two main directories:
COMPONENT_BEFORE_PUBLISHING: contains the component library from which I am running "npm publish"
WHAT_IS_IMPORTED_INTO_NODE_MODULES: contains the resulting directory that is being imported into the node_modules directory of my npm-test project
Again, any help that anyone could provide would be extremely, extremely appreciated! Really, I would be eternally grateful.

If you are %100 sure that ALL of your consumers will import your components, modules ...etc from a TS project such as angular-cli. You can publish your TS source directly without transpiling. Ie. you'll be publishing static .ts files that can be imported in any project that will do the transpiling for you.
However, if your want your library to also be consumed as a JS es5 or es6 module, then you should transpile.
Also, you can try the angular compiler ngc instead of the typescript compiler tsc? ngc is a wrapper around tsc. You could start there, There are many library starters put there that can help you start an angular library and get it optimized for AOT compilation.

Related

"You may need an additional loader to handle the result of these loaders." error ( React, Typescript )

So I have package 1 that I wrote in Typescript that contains mocha tests and I'm pretty sure that it works as it should. I push all the code to the git provider and pull it via npm on package 2. When I start React with Typescript on package 2, I get the following:
I tried adding webpack.config.js, various tsconfig.json configuration changes and multiple npm commands that are connected to cache cleaning and reinstalling but nothing works. This error is just plain weird because, from what I know, there shouldn't be any compilation errors regarding class variables.
FIX
This was a very quick fix. So, in short, if the provider with which you started your Typescript application doesn't provide you with webpack or babel file you will have to transpile any module from node_modules into Javascript that you try to import. In this case I just transpiled package 1 and package 2 worked perfectly.

React app is failing to compile, it appears typescript not being transpiled to JS?

I am working on a react app with a couple of colleagues, and after the latest pull I am no longer able to compile the app, but my colleagues are not having any issues.
On my end the app fails to compile because some #material-ui components are displayed as missing in the node_modules/#material-ui directory. However, when I search the folder, I see the files there, they are just shown in typescript format instead of js. However, when comparing my working directory with a colleague's it appears there are also files completely missing on my end that exists on theirs.
For example, when the app fails to compile I see this:
Failed to Compile
./node_modules/#material-ui/core/TextField/TextField.js
Module not found: Can't resolve '../FilledInput' in
'..../node_modules/#material-ui/core/TextField'
When I search this folder, the file is there but labelled 'FilledInput.d.ts'.
Has anyone encountered something like this? I have recompiled the app, and deleted the branch and recloned from remote but the issue remains.
Thanks
Have you tried removing node_modules and installing dependencies again?
Does npm install give any peer dependency warnings? Does this help?
npm i #material-ui/core --save

'Failed to minify the code from this file' appearing in create-react-app when trying to build production

I have created a react project using Create-React-App and now would like generate the production build. When I use npm run build I am getting the error:
Failed to minify the code from this file:
./node_modules/pify/index.js:3
Create-React-App suggests the following corses of action:
To resolve this:
Open an issue on the dependency's issue tracker and ask that the package be published pre-compiled.
Fork the package and publish a corrected version yourself.
If the dependency is small enough, copy it to your src/ folder and treat it as application code.
will take to long and seems to already be a issue (#50) raised for pify.
I am not sure how I would approach but I think it may be the best option
is not going to work because it is a dependency of a different package.
What I am looking for is come guidance on how to solve this solution before I use option 2 and rewrite a whole package.
I belive the solution would involve ejecting from create-react-app and messing with the webpack config file.

How to convert React related node packages in npmjs.com repository to ES5?

As a newbie I am trying to understand what the logic is under the hoods for react packages in npmjs.com repository.
I find it a little bit strange since some modules that I install works flawlessly with my application (such as react-motion), where some reject to work by giving Uncaught SyntaxError: Unexpected token import error (such as react-sortable-pane).
What I understood up to now is it has something to do with ES5. The modules that are implemented with ES6 or ES7 must be converted to ES5.
My question is, how can I understand if a package is not ES5 compatible and what can I do to convert it to ES5 during or after I used yarn add command to install the package to my node_modulesdirectory?
TL:DR Transpile your code or use:
import { SortablePane, Pane } from 'react-sortable-pane/lib/react-sortable-pane.es5';
First things first.
Two main folders Src and Lib
A common convention for javascript projects is to put all of your development code into a folder called src. This folder may contain code such as ES5 or ES6 depending on what the developer wants to work with.
The other main folder is usually called lib which contains all code from src that is transpiled (with babel for example from ES6 to ES5), converted and usually bundled (webpack minify for example) so that it can work in the browsers that that npm package supports (varies from package to package obviously). This folder only contains code that is relevant to the user using the package, i.e. all tests are not converted and bundled because their is no reason to.
Entry Point
The other important part for npm packages is the entry point for the npm package. By default NodeJS will look for an index.js file in the imported package (I think). This can be overwritten by supplying the main key in package.json.
Example in react-motion's package.json:
"main": "lib/react-motion.js"
We can see that this points to lib. But where is the lib folder on their Github??? It's not their because usually you don't want to check in a lib folder to source control because it's just transpiled for the npm package.
We can confirm this by installing react-motion and looking in node_modules/react-motion. The lib folder here exists with transpiled code that is ready to be used in any browser without babel.
But why don't all npm packages do this for me!?!??!
Most do and they should do really. I do in my packages.
The react-sortable-plane npm package is using this instead "jsnext:main": "./lib/react-sortable-pane.js" which basically means it uses ES5 syntax everywhere but with import/export and I haven't seen before because it isn't widely used.
See https://github.com/rollup/rollup/wiki/pkg.module#wait-it-just-means-import-and-export--not-other-future-javascript-features
As to why they just use import/export with ES5 features I presume it's because import/export has become standard now but I am not sure.
You will still have to transpile this package if you want older browser support or just import the .es5.js file, e.g:
import { SortablePane, Pane } from 'react-sortable-pane/lib/react-sortable-pane.es5';
Hope this helps. I know it's confusing with so many damn environments like UMD, Common, Node etc...
The solution is to account for any version of Javascript and use a transpiler to make sure that various JS versions which might be in your code and imported modules will be covered by your transpiler's configuration. Going through your modules and trying to figure out which version of Javascript they use isn't a practical exercise. Most projects have a bunch of dependencies, and all those packages have their own dependencies. So you'll end up going down a rabbit hole.
Babel is probably the most well known transpiler. With the right configuration you can have ES5, 6 or 7 code and it will transpile it all into the same JS type so it can run in all standard browser versions.
Basically the answer isn't to try and deduce what ES type your modules are, it's to create a build process that can handle the different types.

Configuration for create-react-app after ejecting to build a component library

I started to build a component library that I want to publish on NPM (and reuse in other apps) by creating a React app using create-react-app. Unfortunately the create-react-app default configuration doesn't seem to support building such component libraries (see these issues). So it seems I have to eject.
Do you have some instructions what to configure after ejecting to make this a component library I can reuse in other apps (I guess some Webpack stuff)?
Re-framing my comments into an answer.
Don't eject! CRA hides a lot of stuff under the hood and ejecting throws it up. It's relatively easier to just clone your src into another project with the tooling setup done.
And it's not very difficult to setup one yourself! Here's the things you will need to do:
Basic babel and webpack configuration so your code compiles.
Make sure React and React-DOM are added as external dependencies in your package.json file and added as alias in your webpack.config.js. (A thorough discussion is here.) This is important to ensure you ship the smallest bundles only. Also, React doesn't play well with multiple copies.
Optionally, do the same for any other heavier libraries, e.g. Material-UI, Bootstrap, Lodash etc.
In webpack's configuration, decide how you want your library exports should be? You should be good with UMD.
Add main (and optionally module) entries in your package.json to let npm imports know where the components should be imported from.
Publish it.
Done!
Or, you can simply clone one of these super thin component projects and put in your components there -
https://github.com/wangzuo/react-progress-label
https://github.com/aaronshaf/react-toggle
There are more complete starter-kits as well, but IMO it's important to first know the details yourself before you abstract them away. Once you are familiar with the process, you should try leveraging the kits too as they go much beyond the basics, like test integration, react-storybook support and great npm publishing support.
UPDATES:
The purpose of CRA is to allow quick experimentation and on-boarding to React development, without going through the (somewhat complicated to a beginner) tooling setup. The intended use case of CRA, as denoted by the "App" in the name, is the whole app, not a component. Although developing anything built on language features like ES6 takes some tooling, an app typically takes more setup than a component. E.g. you also need a server component which hosts the generated code. CRA does all this and more for you.
And if you are working on an app, you will eject when you want to take control of the server side of it. It adds value in that case as you will get the basic hosting code auto-generated by CRA during eject.
To address test needs, CRA also has Jest integration, which is a test runner having React specific features like snapshot testing. Again, setting it up manually with your build pipeline is a handful and CRA once again hides all of this complexity from you, so you can simply focus on writing the tests.
This is super simple - you don't actually need webpack if you want to publish a package. Don't install it just for that if you don't want to.
If you use ES6:
You can use a simple script to create a dist folder that babel will create the files after transpiling:
"scripts": {
// other scripts
// .. might want to change "rm -rf" below if you're on a PC
"build:production": "rm -rf es && cross-env NODE_ENV=production node_modules/.bin/babel ./src -d es"
},
What this does is:
Remove the es folder, which is a build folder.
Runs babel for your files (in case they are located in src folder, change it to wherever your files reside) and create the es folder with the transpiled files.
In order to use the script above you need to install the following dependencies:
babel-cli / babel-core / babel-preset-es2015 / cross-env
Make sure you have a .babelrc file so that babel will work:
{
"presets": [
["es2015", { "modules": false }]
]
}
Now all you have to do (after running npm run build:production) is to run:
npm publish
And your library is published in npm. This is also the command you run if you want to update, just don't forget to update the version number in your package.json.
In case you have files you dont want published to npm, just have a file in your root called .npmignore (similar to .gitignore) and list everything you want excluded.
If you don't use ES6:
In this case you don't need to transpile anything, just go straight to the npm publish section above and run it on the root folder you want published.
create-react-app is meant for quick setting up and development of apps, not really for development of libraries. For one thing, create-react-app creates an index.html file when building, which is usually not needed by libraries. Libraries require a different set of configuration (much less).
I faced this problem myself and have written a React component boilerplate for writing and publishing React components: https://github.com/yangshun/react-component-starter, after referencing how popular ES6 libraries were written, such as Redux.
Pros:
Similar to create-react-app, batteries are included
It has got all the important areas covered: development, linting, testing, and distributing
Minimal configuration
Babel for transpilation to ES5 and CommonJS format
ESLint included and configured
Jest tests examples
Webpack configuration that compiles to UMD
React Storybook for quick development of the components
Support for stylesheet distribution alongside your component
Cons:
Highly opinionated in terms of choice of tooling; they follow the choices set by create-react-app.
Have to manually update each package dependencies in future (you'll face this issue if you did eject anyways)
There is minimal configuration included and setup is easy. The various webpack, Babel and ESLint configurations should be quite understandable.
Hope this will be helpful to you. Feel free to give suggestions and comments on how it can be improved.

Resources