I've build an UI component using react/ES6 and I need to reuse it for several other projects.
So I thought it could be a nice little npm package.
Turns out the default for npm packages seems to be:
Put ES6 modules under /src
Have a separate /lib where the transpiled files live
On every release transpile those modules to ES5
From my point of view this is some (needless?) overhead. The projects that will use the package will be written using ES6 as well, so there is no need to transpile the dependency.
Is there any way to bundle ES6 modules in an npm package and skip the transpile process - and accept the fact that projects need to use ES6 in order to to add this dependency?
Edit to clarify
#D-reaper right, fair enough. My problem is the importing side. I've build a package that includes Project.jsx. When attempting to import it I get the following error message:
ERROR in ./node_modules/foo/Project.jsx
Module parse failed: /../node_modules/foo/Project.jsx Unexpected token (14:11)
You may need an appropriate loader to handle this file type.
So my guess is, that webpack/babel can't handle the import of ES6 modules correctly, since they expect npm packages to include ES5 - is that a correct assumption? Can I work around that?
I will use https://github.com/insin/nwb to put my react components into npm packages.
why don't you try Bit as to share your components. You can use bit's compilers or your owns if you have custom use case. You can read a little more https://codeburst.io/start-using-bit-to-build-react-apps-like-lego-7e14920f8de2
Related
I'm seeing some API drift between the type declarations/definitions of a typescript DefinitelyTyped module (e.g. #types/prompts) and the javascript module it is meant to 'wrap'. How is one supposed to correctly pair versions for the the types package, and the version for the underlying javascript package?
Say I add a dependency on #types/prompts": "^2.0.14" in my package.json. How do I make sure I get the right version of javascript npm package that goes with it?
The npm package #types/prompts has no explicit dependency on the javascript module in its package.json, and there doesn't seem to be any mention of compatibility that I can see in the README.
All I've found is a loose comment in #types/prompts's index.d.ts mentioning:
// Type definitions for prompts 2.0
// Project: https://github.com/terkelg/prompts
...
Is there a convention we're supposed to follow? I'd be interested in hearing about a general approach, not necessarily just for this example.
References:
typescript types package: https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/prompts
upstream javascript module: https://github.com/terkelg/prompts
In my experience, usually major and minor versions are being kept in sync between the upstream package and its #types package. Then the patch version would not match, due to the need of being able to fix a bug.
An example with react:
The current version of react is 17.0.2
The current version of #types/react is 17.0.37
The only part which isn't super clear is when a patch of the upstream package changes types. Is that change already applied in the types package?
So for example react decides to publish 17.0.3 which contains a non-breaking difference in types. How do we know if 17.0.37 includes that change? But for that, it's probably a better idea for react to actually publish 17.1.0 to address that new change.
I'm having a private typescript module that is a dependency of another major project. This dependency is achieved by having the typescript repository as sub-module and installed using npm to the local sub-folder. The typescript module can compile into JavaScript on its dist folder and by doing so the major module that consumes it can make use of it without issues. But here is my problem, the dist folder isn't committed to the typescript repository.
What should be the workflow to follow in order to consume this typescript module from a JavaScript-only major project? The best I can think at this moment is to instruct someone, or something, to run the $ tsc command before using the major project but it's "annoying" since it isn't a transparent step. If this is a weird approach, what would be a more ideal approach? Thanks everyone.
You have a couple of options.
Assuming you're not planning to have a private npm registry using e.g. Verdaccio you can simply commit the dist folder. This is definitely the simplest option and it's not completely unheard of, I'd probably go with that option.
This solution is actually quite unusual, but it's pretty clever and it works. You could add a postinstall script in package.json of your TypeScript package that would run tsc after installing the package. The downside is that you'd have to add typescript as your dependency, which is not ideal (it should generally be a dev dependency, in which case it wouldn't be installed in the project using the package), but for some it might not be a big deal at all.
Instead of installing the package, you could use npm link and then have a script in your main project that would compile it. You'd have to run it every time something changes in that package, though. You could also append it to your npm start script, so it runs before it, e.g. "start": "npm compile-package && webpack" (assuming your current start script is "start": "webpack"). It doesn't scale very well though.
If your Javascript project uses Babel (and I'd assume so considering you said it's a "major" project) you could change its config so it transpiles Typescript for you using #babel/plugin-transform-typescript, however it can be a bit complicated, IIRC e.g. projects created with create-react-app by default don't recompile the code from node_modules.
There are probably more solutions, but I'd probably go with 1 or 2.
I have monorepo built with Lerna. It has following structure:
packages
- create-react-app-example
- utils
create-react-app-example is like what create-react-app produces. I.e. it uses webpack for transpiling ES6/ES7 code, has hot-module-replacement on files changes etc;
utils package has just 1 file with some utility function. And this function is used from inside create-react-app-example package; It doesn't use Webpack, Babel or any other tool;
So, all pretty simple.
But I have hard times trying to configure comfortable development environment.
So there few things I want:
to be able to use es6/es7 code inside utils package (code of this package should be transpiled somehow);
automatic hot updates of main module when something changes in utils package;
The only thing came to my mind is to tweak webpack.config.js of create-react-app-example:
change setting of babel loader, so it will not exclude node_modules/utils folder and will transpile it;
and change parameters of webpack watch so it will detect changes in both packages
But I don't like solution above, it looks dirty for me.
May be there some more elegant solution?
Or may be I should also add webpack.config to utils package and somehow use it as library? If I remember correctly Webpack has such functionality.
Thanks
to be able to use es6/es7 code inside utils package (code of this
package should be transpiled somehow);
If you really want to keep utils as a separate package, just configure babel to transpile it separately from the CRA app. You can do this using the babel cli, here is an example of how to do it: https://github.com/babel/example-node-server
automatic hot updates of main module when something changes in utils
package;
Your idea to configure webpack watch sounds right. Docs here
You will likely end up with 2 watches: babel transpiling the utils package, and webpack for building and bundling the CRA app.
I want to use the Perf stuff. It seems that if I do:
var React = require('react/addons');
in my own modules then libraries (react-bootstrap, react-router etc.) end up using another copy of plain react and things break. I am using browserify.
Is there a fix or another way to do this?
Requiring react and react/addons will give you the same object. react/addons requires the same module that react does (lib/React), and react/addons even mutates that object so that anyone requiring react will get the addons as well.
If you end up with multiple versions of React in your bundle, it's because the libraries you use have react as a dependency instead of a peer dependency. You should use npm dedupe to avoid that. But react-router has react as a peer dependency, so react-router will get the same react module instance as your module (with the addons). Don't know about the other packages you use that depend on React though.
It turns out the problem was with my gulpfile. Tx for the comments about looking for a browserify shim that lead me to the solution:
My browserify task (from React JS workflow, part 2) builds separate vendors.js (libs) and main.js (my app) bundles during development using browserify.external(..) to exclude the libs from main.js. I just had to add "react/addons" as an external lib along with "react".
The issue is explained here:
https://github.com/substack/node-browserify/issues/1161
There are a ton of packages out there that have this all bundled up but I dont like the way they set up the projects and such so I was reading the Reactjs docs on installing with npm and my confusion is:
After installing it using npm install react or adding react to
package.json
Do I add this to the "devDependencies": {} or ...
for the require statement to work, do I need to include requirejs?
Can I just do grunt serv to start everything and auto compile the jsx or do I need to do this? (it seems like that might be answered for me ..... but how can I get it to auto compile the jsx when I run grunt serv)
I ask these questions and state I don't like the existing yo ... commands for this because they don't play nicely with bacbone.js So I was going to set this up my self. if there are any repos out there for yeoman that do this for me please point me to them.
dependencies vs devDependencies: for npm package.json, devDependencies are mainly used for the tooling around working on the project itself: testing tool chain and project building modules, for example. Things you'd often see in there: Mocha, Grunt, etc. So mostly for repo contributors and alike. As a consumer of React, you'd put it in dependencies, which are for modules that your code actually needs in order to work.
require isn't for requirejs. The naming clash is unfortunate. require() is part of CommonJS. Node uses CommonJS. Browserify too. Here, it's assuming that you're using Browserify, or maybe doing server-side React with Node.
I'm not sure what you've set up to use with grunt serve. There's nothing magical that makes it work by default. You do need to do what the link said. The --watch option will look for changes to your files and auto compile the jsx to js.
Hope that helps!