Why I have too many packages inside my node_modules? - npm

I am new, and when i first created my app based on the documentation using npm create-react-app i found it there were a lot of package included inside folder node_module when i code and i only use react and react DOM and etc from the basic.
node_modules
acorn
timer
ansi
and many more
I wonder if anyone can help my how to understand each use inside the node_module or where can i find the documentation for each use?
or how can i just reduce to what i want to use only to decrease the app size?

The answers are 2:
because you're using an automated scaffolding tool, which essentially does everything for you, and, you have just to code, it is supposed to locally deploy all the packages it needs to work (for example webpack is needed to bundle your code, babel to transpile it, ...
under node_modules you will find all the packages of the whole app. That's means you will find both your dependencies and the dependencies of your dependencies (this rule has some exceptions and you can find them in the npm documentation.
example:
// your code depends on A
var dependency = require('A');
// but then, inside your A dependency you can also find something similar to:
var b = require('B');
how can i just reduce to what i want to use only to decrease the app size?
You basically can't do it. They are all needed.

Most of the libraries that we pull from npm have dependencies. You may use only react and react-dom but there are react-scripts that require lots of stuff. I don't think that you have to worry about the size of the node_modules. That's not what you are suppose to ship in production.
If you want to see what are these all modules about you may open their folder and fine README.md file.

Related

If I install lodash.minby does it means it just installs this specific function?

I am getting rid of lodash, so some stuff I am redoing in es6 and other like this one I would like to keep but just this one function.
I see there is this npm https://www.npmjs.com/package/lodash.minby but im not sure if i install this it will only install this, or the whole library, can anyone please confirm?
Thanks.
From the documentation:
The lodash method _.minBy exported as a Node.js module.
So, yes, it just installs this specific function from lodash
Yes, if you install lodash.minby, at the time of this writing, you will get version 4.6.0 which contains a package.json file, a README.md file, a LICENSE file, and an index.js file. It has no other dependencies, so that is all you will get. The index.js file is over 2000 lines long, but that's what it takes apparently to implement the functionality.
In contrast, at the time of this writing, npm install lodash will give you version 4.17.21 which contains over 44000 lines of JavaScript spread out across many files. So that's about 22 times as large.

Do I really need all these dependencies?

I'm new to react native, and I notice when I create a new project using react-native init projectName that it creates something like 600+ folders in the node_modules folder.
I was sort of expecting to be able to create a bare bones project with only essential dependencies and then add new stuff as necessary as I would do in any other language. I don't really know what any of the dependencies are already, and of the half a dozen or so things I've needed so far I've had to install a new dependency and haven't used anything from here except for the essential react and react-native modules.
Is this how you guys all start your projects, or does this contain hundreds of extras that don't need to be in my project, and if so how do I create a bare bones project? I tried looking at options for the init command and saw one called skip-install that looked like it would install w/o installing all the dependencies but it seems to have had no effect.
Node Module folder contains all the dependencies of the whole app. You can check this in every folder's Readme.md file. If you add any new library in your package.json, everything will be listed there.
To start with, create-react-app contains
a compiler (Babel),
a bundler (Webpack),
a linter (ESLint),
a styling pipeline tool (SCSS),
a development server with live reloading,
a code minifier,
a test runner (Jest),

Creating a single Vue component inside a larger project

I have a PHP project that uses Kirby CMS. I also use Gulp for building my assets. Now, I need to add a calculator on the homepage that is complex enough to justify the usage of Vue. How would I incorporate Vue in my project without introducing a ton of new tooling? All I want is a simple Single File Component basically. I have:
<div id="calculator"></div>
and I want the component to be rendered there. Nothing more.
After some consideration, I came up with the following options but found issues with each of them:
Use the Vue CLI for instant prototyping. That's the closest solution for my use case, but I can't easily develop the component. If I use vue serve, I get to see the component isolated in a new page. The issue lies in the fact the component isn't a part of my project's page. It's not affected by its stylesheets, layout, and other scripts. I can't know if it'll work properly once I build it and view it in my project. Running vue build on each change would be pretty painful and time consuming. Sadly, vue watch isn't a thing, which leads me to:
Creating a project and using Vue CLI Service. If I create a project, I'd be able to run vue-cli-service build --watch and have my component automatically refresh on each change of its source file. While developing the component, I simply make a change, wait for it to compile, and refresh my project in the browser to see the modified component in action. While that would work, it introduces a bunch of node_modules inside my project, along with a package.json. I feel that's too much for just a single component. It would pollute the project more than I'd like:
assets/
js/
build/
calculator/
dist/
node_modules/ # modules here
public/ # I don't need that
package.json # package here
package-lock.json
App.vue
scripts/
main.js
content/
site/
node_modules/ # modules here as well
panel/
package.json # package here as well
package-lock.json
index.php
I would basically have a project within a project.
Use vueify to compile the component with Browserify and Gulp (which I already use). While this appears OK, vueify is deprecated and not supported. Besides, I'd have to add a bunch of stuff to my gulpfile.js in order to use Babel + ESLint for the component.
How do I set up Vue in such a way that I'm able to develop a very simple component as a part of a larger project with as little friction as possible?
If anyone has dealt with a similar problem, how did they solve it?
I ended up using the second approach I mentioned in my question with one small twist - I initialized the Vue project in my main project. I merged them.
I opened the parent folder of my project in a terminal.
I ran vue create my-project where my-project was the actual folder name of my project. The CLI asked if it should overwrite the project or merge it. I chose merge.
After the project was created, my old package.json was overwritten and only had the Vue dependencies listed in it.
I reverted my old package.json and installed these packages: #vue/cli-plugin-babel, #vue/cli-service, vue-template-compiler, and vue.
I added the following npm script in my package.json:
"scripts": {
"calculator": "vue-cli-service build assets/js/calculator/main.js --watch --dest assets/js/calculator/build"
}
Result
My project's folder structure remained the same, except for a few new packages in node_modules. I put my component files in assets/js/calculator/. There, I have main.js which is the main component script, and build which is a folder containing the processed component.
I have:
<div id="calculator"></div>
in my page, and:
<script src="/assets/js/calculator/build/app.js"></script>
in the footer. When I open the page, the component is rendered correctly.
To modify the component, I simply run npm run calculator in a terminal, which spins up the CLI service. It monitors the main.js file and builds the component on each change. Once the build is complete (which happens in under a second), I refresh the page and the updated component is there.
Conclusion
I believe that's the smoothest way to handle this use case. It didn't bloat the project, all dependencies were listed, and the development experience is great. The part where my package.json got overwritten was a bit concerning, but other than that - it worked perfectly. If there's a better way to do this, please leave an answer!
This is probably not the answer you're looking for but if I were you I'd look into inline templates and x-templates as they seem well suited to your use case.
Also have a look at this blog post. It offers a nice write up about the different template authoring methods in Vue and their pros/cons.

When using Webpack to resolve directly to a sibling NPM project, how can I specify a resolve order wrt which node_modules to look at first?

I have two npm projects, project-a and project-b. They both publish and ought to be able to be directly depended upon by any npm project in my company. project-a depends on project-b. They both live as siblings in the same Git repo.
I want to directly import certain components from project-b into project-a. I'm very close -- by specifying a resolve.alias in project-a that looks like project-b: path.resolve(__dirname, '../project-b/entrypoint.js') I can pull in what entrypoint.js offers. However, when Webpack attempts to resolve what entrypoint imports, it looks first in project-b/node_modules. This is a problem for two reasons: we use React, so this pulls in multiple copies of React (project-a/node_modules/react and project-b/node_modules/react), which React users know will break the UI, and similarly it pulls in multiple copies of any shared dependency, of which there are many, leading to a considerable amount of otherwise benign bloat in the Webpack artifact of project-a.
My hunch is there must be a way to tell webpack to, when resolving imports in project-b, first look in project-a and failing that go ahead and look in project-b. This way it'll first look in project-a/node_modules for react whether the import statement is in project-a or project-b, leading to only project-a/node_modules copies of shared dependencies in project-a's artifact, while successfully allowing unique project-b dependencies / components to be resolved. I've played around a bunch with resolve.root, resolve.modulesDirectories, and resolve.fallback, but haven't been able to achieve what I want.
Any ideas?
I ran into a similar issue in my project, also with multiple copies of React being included in the bundle.
The solution is quite simple -- add this to your webpack (version 2) configuration under the resolve key:
modules: [path.resolve(__dirname, "node_modules"), "node_modules"]
This instructs webpack to resolve in node_modules within the build directory before resolving in node_modules in other directories. In your case, this should mean that the module is grabbed from project-a/node_modules instead of project-b/node_modules.
You can find more documentation here.

How to blacklist specific node_modules of my package's dependencies in react-native's packager?

I'm putting together a streamlined development process with react and react-native that:
encourages packages,
uses babel to transform es6 to js (it compiles before publishing/installing),
has a playground that let's you play with both native and web components.
The web part of it is perfectly fine. It's the native one that's causing issues and it has to do with react-native's packager.
The bottom line is: if the package is either linked through npm link or required directly from the playground as in require('../../') react-native's dependency resolver will go forever trying to identify dependencies inside my package's node_modules, most times it never finishes doing it.
The temporary solution I've found is to install the package in playground but this involves re-installing it every time I do an update, which isn't great because you can't see your changes right away (even if it would be automated, it would take time).
I believe that a better solution would be to ask the dependency resolver to ignore those specific modules I don't need (those in devDependencies mainly!). I tried mangling react-native/packager/blacklist.js by adding paths to that list and even putting checks against the dependency resolver but none of that would work.
Can someone with more experience with the packager give me a hint as to how I'd go about making the dependency resolver pass? Alternatively, it would be great if the packager could be separated and the transform process left to choice but I don't know if that would be doable either.
I found out the following solution, based on the comment in default.config.js:
* If you need to override any of this functions do so by defining the file
* `rn-cli.config.js` on the root of your project with the functions you need
* to tweak.
Create a rn-cli.config.js in the root of your project with the following contents:
var blacklist = require('react-native/packager/blacklist');
var config = {
getBlacklistRE(platform) {
return blacklist([
/node_modules\/my-package\/excluded-dir\/.*/
]);
}
};
module.exports = config;
The second argument to the blacklist function is an additional list of blacklisted paths, which can be regular expressions. See react-native/packager/blacklist.js for more examples.