Configuring Lerna for development environment: using shared package - javascript

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.

Related

Workflow to use a sub-module typescript written module into a non-typescript module?

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.

Why use Webpack to bundle applications that run in node environment

For me, Webpack is a bundler for "web" since browsers don't have good support for js module system. Thus using Webpack we could still use "module" way to develop and pack them for browsers.
Webpack has a config option target
module.exports = {
target: 'node'
};
using node webpack will compile for usage in a Node.js-like environment
But NodeJS already support CommonJS modules, why need Webpack to build something that runs in NodeJS environment?
Besides, if you want to compile your javascript, for example, using the ES module, you could just use babel to do so, using es module transform plugins or proper presets.
Why use Webpack, set the target to node and then use babel loader... instead of using babel directly?
I cannot think of the use case of using Webpack to bundle application running in node.
One reason I can think of when to use webpack for node is when you have a node_modules package where it's not compiled yet (Still in ES6).
babel-node won't be able to help you bundle the node_modules packages that need to be transpiled along with the rest of your code
I had to go through this process.. ): This scenario is helpful in Yarn Workspaces where you want your server to depend on another package in your workspace. Where your server will re-update whenever you make changes in the other package with the help of webpack
How to include a few node_modules package in babel-node
Having a single server.js output
instant deployable on a server
no worry about mismatching dependencies compared to your dev environment.

transpile services module angular 2

I have a common module in an angular 2 application. This is how the project is structured:
main
--app
/common
--config
//.ts configs for modules
--services
//angular services
--models
--store
//ngrx store
/component1
/component2
app.module.ts
main.ts
--js
//systemjs dependencies
Gruntfile.js
package.json
tconfig.json
The project is configured to transpile to bundle.js and works as expected. However, now I want to bundle out the contents of common folder and package it in isolation. Such that, I can just load its dependency using system js, and then include it is app.module.ts to use in components.
I need help in getting started, is it some gruntfile/tsconfig changes that I need to make? Or would I have to create a separate package.json/index.ts to transpile .ts dependencies?
The feature I believe you are looking for is the Bundle Arithmetic feature of the systemjs-builder. It is built into SystemJS and works very well.
However, it will mean using SystemJS to bundle your app instead of a grunt.
This has many advantages and actually simplifies many scenarios, like your specific use case, but it may take you a little while to get everything set up.
TypeScript does not support splitting bundles at this time.
Splitting your app into multiple npm packages is not necessary and will introduce significant complexity into development process if your application is small.

Reusing my own JavaScript modules without using relative paths

I am new to JavaScript development and could do with some advice regarding how best to work with multiple modules of my own creation.
Module1
--src
----a.js
----b.js
Module2
--src
----c.js
----d.js
Module3
--src
----e.js
----f.js
Module4
--src
----g.js
----h.js
Now each module is a collection of js files that use module.exports to export functions that they need to.
In this example Module1 and Module2 are library module. Module2 depends on Module1. Both of these modules are platform agnostic and can be ran inside a browser or nodejs.
Module3 is a project module which depends on both Module2 and Module1. It is designed for a browser and uses browserify to combine them all into a bundle.
Module4 is another project module which also depends on Module2 and Module1. This is designed to run under nodejs.
Each module has its own git repo.
Now the problem I am having is to do with relative paths inside the require. For example c.js currently does require("../../Module1/src/a.js"); Similarly h.js does require("../../Module2/src/c.js");
This causes foldering structure to be an absolute pain and each project has to be cloned from git in the correct setup.
The following is what I am trying to achieve.
To do away with relative paths so I simply do require ("ModuleX/src/foo.js"); This needs to work with both browserify and nodejs.
To clone a project module from git and have it get all of its dependent modules (perhaps git submodules?). Not caring about folder structure as this should be solved using the point mentioned above.
Once a project and it's dependent modules have been cloned to be able to edit each of these modules, make changes and push them to their individual git repo.
I imagine what I am trying to do is pretty standard. Creating my own modules and reusing them in different projects. Am I trying to go about solving it in the standard way? I've read that there are different ways to achieve this using NODE_PATH which is supported by both node and browserify but both discourage it. Browserify supports a paths option but doesn't work for node. Also read about putting the modules inside node_modules but not sure how that would help with relative paths.
Any advice would be greatly appreciated
Thanks
What you probably want to do is commit your reusable code to git (here GitHub) and then npm install <git remote url>:. An example would be npm install git+https://isaacs#github.com/npm/npm.git. On the other hand your repo needs a package.json and a index.js holding your code or pointing to it. Alternatively you could define the location of your main file in the package.json via main:"" key.
The dependencies between those projects would be defined in the respective package.jsons. Upon install npm does it's magic to avoid circular dependencies, caching etc.
Once you've done all that you would be able to just var x = require("ModuleX") to get ModuleX/src/foo.js if you so wish to.
Alternatively use npms private modules.

When it comes to using react with yeoman

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!

Categories