Node/NPM managing local packages - node.js

TL;DR How do I configure different "sub-modules" in a modular node.js project to refer to one another as simply as possible?
I'm trying to wrap my head around local packages for NPM, specifically as they relate to a modular project.
I'm building a web app with a front end and a back end API. These need to share a package which exports simple models. My project directory structure looks like this:
package
├── api
│   ├── dist
│   │   └── <compiled files>
│   ├── node_modules
│   │   └── ...
│   ├── package.json
│   └── src
│   └── <source files>
├── application
│   ├── dist
│   │   └── <compiled files>
│   ├── node_modules
│   │   └── ...
│   ├── package.json
│   └── src
│   └── <source files>
└── models
   ├── dist
    │   └── <compiled files>
   ├── node_modules
   │   └── ...
   ├── package.json
   └── src
   └── <source files>
Both the API and application projects are going to use models, so I abstracted that code to a separate sub-module within my project.
I've read the documentation for npm link and that seems to be the right approach because, as I understand it, it symlinks the package in the node_modules dir. This gives access to the code as it exists right now, instead of installing a copy in node_modules. Sounds like what I need, but there is a wrinkle: I'm working on this project from a couple of different places: my laptop, my office at work, and occasionally from home. In addition, others will be contributing to this project in the future.
I would like to make it as simple as possible for a new contributor to get up and running with development.
Currently, a new contributor goes through these steps:
clone the repository
cd into the models dir
run npm install
npm link
cd into the api dir
run npm install
npm link models
cd into the application dir
run npm install
npm link models
start working
What I would like to do (and I think npm should be capable of doing) is:
clone the repository
cd into the models dir
run npm install
cd into the api dir
run npm install
cd into the application dir
run npm install
start working
I could write a script to do this, but it seems like an obvious use case for npm and I suspect that it's probably capable of doing something like this. I think I may be overlooking something because I'm not finding it in the documentation.

There may be better ways to solve this, but..
One possibility is to create a package.json in the root of your project, which handles all of the initialization of your project.
package
├── package.json
And the contents of the package.json has no dependencies, but scripts to link and install dependencies for all of the submodules using just npm install from the package directory.
If you put the following in a package.json in your package folder
{
"name": "package-name",
"version": "1.0.0",
"description": "Some description",
"scripts": {
"init-models": "cd ./models && npm install && npm link",
"init-api": "cd ./api && npm install && npm link",
"init-app": "cd ./application && npm install && npm link",
"postinstall": "npm run init-models && npm run init-api && npm run init-app"
}
}
You will just need to npm install to initialize the whole project.

Related

Installing quill-image-resize-module results in creating "node_modules" inside of it with many modules

I'm trying to install quill-image-resize-module via NPM. I have tried these commands npm install --save quill-image-resize-module, npm install quill-image-resize-module, npm install -g quill-image-resize-module.
All of them resulted in the same result. The result is, that the folder quill-image-resize-module getting created inside node_modules, then another node_modules gets created inside quill-image-resize-module. Inside this new, sub node_modules, many folders get created, e.g. acorn, array-uniq, lodash.
To sum up the issue, the NPM isn't installing the package, instead he's downloading many packages and putting them in a new folder inside quill-image-resize-module. Therefore, I'm unable to import the package.
import ImageResize from 'quill-image-resize-module'
This results in an error. The package does exist, but it doesn't have the files. It has another subfolder, and inside it, many other folders.
Log based on Old Pro's answer:
ERROR in ./resources/js/app.js
Module not found: Error: Can't resolve 'quill-image-resize-module' in 'C:\xampp\htdocs\myapp\resources\js'
# ./resources/js/app.js 112:0-36
# multi ./resources/js/app.js ./resources/sass/app.scss
Works for me using Node 8.14.0 if I use require instead of import. Please post the error you get when you run
node -e 'require("quill-image-resize-module")'
My installation of quill-image-resize-module has 425 directories under ./node_modules/quill-image-resize-module/node_modules/ and the error I get is about window being undefined, which is normal for node but indicates that quill is expecting to be run in a browser, so your real issue may have nothing to do with the npm install.
I will suggest you delete your node_modules then you run npm i quill-image-resize-module --save, this should take a while to install, after it is successfully installed, you should have a tree of this:-
node_modules
├── quill-image-resize-module
│   ├── demo
│   │   ├── index.html
│   │   └── script.js
│   ├── node_modules
│   │   └── //Contains a long list of other dependencies
│   └── src
│      ├── modules
│      │   ├── BaseModule.js
│      │   ├── DisplaySize.js
│      │   ├── Resize.js
│      │   └── Toolbar.js
│      │
│ ├── DefaultOptions.js
│      └── ImageResize.js
│  
|
├── .editorconfig
├── .eslintrc
├── .npmignore
├── CHANGELOG.md
├── image-resize.min.js
├── npm-shrinkwrap.json
├── package.json
├── README.md
└── webpack.config.js
After which you can import the package as shown in the usage below:
Usage
Webpack/ES6
import Quill from 'quill';
import { ImageResize } from 'quill-image-resize-module';
Quill.register('modules/imageResize', ImageResize);
const quill = new Quill(editor, {
// ...
modules: {
// ...
imageResize: {
// See optional "config" below
}
}
});
This should solve your issue, but you can get to read more on quill-image-resize-module.
Edit: Give this NPM package a shot npm i quill-image-resize or yarn add quill-image-resize
This is the proper CLI command for installing the dependency. npm i #appsflare/quill-image-resize-module
It was probably installing many other modules from other repos or something else since it was lacking the reference to the appsflare mono.
https://www.npmjs.com/package/#appsflare/quill-image-resize-module
This import { ImageResize } from 'quill-image-resize-module'; should work after using the proper install command, per the NPM documents.
Good luck, I hope it helps.
You can install npm i --save quill-image-resize-vue and use below code in your component:
import { VueEditor,Quill } from 'vue2-editor'
import { ImageDrop } from 'quill-image-drop-module';
import ImageResize from 'quill-image-resize-vue';
Quill.register("modules/imageDrop", ImageDrop);
Quill.register("modules/imageResize", ImageResize);
export default {
name: 'ImageResize',
components: { VueEditor},
data() {
return {
content: '<h2>Here goes your content</h2>',
editorSettings: {
modules: {
imageDrop: true,
imageResize: {},
}
}
}
},
}
Official URL: Quill image resize vue

npm install: Is there a way to ignore a particular dependency in package.json

I am currently trying to create a docker container for a node.js project that contains a local dependency. This seems to cause an issue with docker so as a workaround I am trying to just copy the local dependency folders and just ignore their dependency entries in the package.json file. Is there a way to specify dependencies I would like to ignore and have npm install run and skip those enties?
That can be done using devDependencies
The npm modules which you require only to develop, e.g.: unit tests, Coffeescript to Javascript transpilation, minification etc,make the required module a devDependency.
To skip Installation of devDepenencies pass --production flag to npm install,with the --production flag(or NODE_ENV environment variable set to production) npm will not install modules listed in devDependencies."
npm install --production
To make any module to be part of devDependencies pass --dev while installing.
npm install packagename --save-dev
It is a common issue, not only with Docker, but also with some cloud deployments. For example deployment to CloudFoundry using standard Node.js buildpack will cause npm install/yarn to run anyway. So, you'll also need to apply some tricks to work with local modules
If you don't mind to switch from NPM to Yarn for dependency management, you can use workspaces feature.
My package.json looks like this:
{
...
"dependencies": {
"some-module-i-want-to-install": "1.0.0",
"another-module-i-want-to-install": "1.0.0",
"#my/local-dependency-one": "1.0.0",
"#my/local-dependency-two": "1.0.0"
},
"workspaces": ["packages/*"]
}
And my project source layout has the following structure:
.
├── index.js
├── package.json
├── packages
│   ├── local-dependency-one
│   │   ├── index.js
│   │   └── package.json
│   └── local-dependency-two
│      ├── index.js
│      └── package.json
└── yarn.lock
After running yarn, modules I want to install are fetched from NPM registry, and local dependencies are installed from packages directory to node_modules.
.
├── index.js
├── node_modules
│   ├── #my
│   │ ├── local-dependency-one
│   │ │ └── ...
│   │ └── local-dependency-two
│   │ └── ...
│   ├── another-module-i-want-to-install
│   │ └── ...
│   └── some-module-i-want-to-install
│   └── ...
├── package.json
├── packages
│   ├── local-dependency-one
│   │   └── ...
│   └── local-dependency-two
│      └── ...
└── yarn.lock
As you can see, I prefer to define my local packages as scoped (#my/...). It is not mandatory, but a best practice. NPM treats scoped packages as private by default, so I don't need to worry that they will be occasionally published or explicitly mark them as private.

How does the #shopify/polaris project get built from github repo to npm dependency?

I'm interested in learning how the #shopify/polaris project in github is built and published to npm. My main questions are:
How are the index.es.js and index.js files being generated? Are those being generated programmatically on my computer, or are they published to npm like this?
What mechanism is preventing the files in the github repo from being downloaded when installed? I don't see a .npmignore in the repo.
Below I have the files in the npm package, and the github, and you can see they're different.
Here's what the polaris project looks like when it's installed via NPM / yarn.
.
├── CHANGELOG.md
├── README.md
├── index.es.js
├── index.js
├── package.json
├── src
├── styles
├── styles.css
├── styles.scss
└── types
Here's what the project looks like on github.
.
├── CHANGELOG.md
├── README.md
├── circle.yml
├── config
├── documentation
├── examples
├── package.json
├── scripts
├── src
├── tests
├── tsconfig.json
├── tslint.json
└── yarn.lock
We use Rollup to generate the different entry files for Polaris. You can see our generic config file here: https://github.com/Shopify/polaris/blob/master/config/rollup/index.js. Note that it does all the work of compiling our TypeScript source files (using TypeScript and Babel), as well as kicking off the work required to bundle our CSS and icons as appropriate. This config generator is then run three times, which you can see here: https://github.com/Shopify/polaris/blob/master/scripts/build.js#L36-L38
The main entry file (.js, and spits out the CSS for our CDN)
The module entry file (.es.js)
The embedded entry file
We then copy these into their final locations for the NPM publish.
As for how we control what files are in the NPM package, we use the files key in our package.json; these are the relevant lines.

How to organize a large single repo node.js app

I have a node.js app using a single git repo, that has various packages. I am trying to make things modularized, and separate.
├── common
│   └── formattr
│   ├── node_modules
│   ├── package.json
│ └── formattr.js
└── providers
├── aws
│   ├── node_modules
│   └── package.json
└── google
├── node_modules
└── package.json
The problem I am running into is that when somebody clones the app, they have to recurse into each package direction and manually run npm install. Additionally, there is lots of wasted resources and duplication, since the package aws might use npm install request but so does the google package. Right now, they both store independ versions.
Finally, there is this problem as well:
// Inside of the aws package, I need formattr. This makes me cry inside.
let format = require('../../common/formattr/formattr');
What is the recommended pattern and structure?

npm install not installing things at /usr/bin

I am trying to install SailsJS with:
$ sudo npm install -g sails
It works, install everything at /home/brunoluiz/npm/lib/node_modules/sails with the following log:
/home/brunoluiz/npm/bin/sails -> /home/brunoluiz/npm/lib/node_modules/sails/bin/sails.js
sails#0.9.16 /home/brunoluiz/npm/lib/node_modules/sails
├── connect-flash#0.1.1
├── pluralize#0.0.5
├── inflection#1.2.5
├── grunt-sails-linker#0.9.5
├── grunt-contrib-clean#0.4.1
├── node-uuid#1.4.0
├── async#0.2.9
├── grunt-contrib-concat#0.3.0
├── grunt-contrib-copy#0.4.1
├── grunt-contrib-coffee#0.7.0
├── ejs-locals#1.0.2
├── ejs#0.8.4
├── underscore.string#2.3.0
├── coffee-script#1.6.2
├── lodash#2.4.1
├── i18n#0.4.1 (debug#0.8.0, sprintf#0.1.3)
├── optimist#0.3.4 (wordwrap#0.0.2)
├── include-all#0.1.2 (underscore.string#2.3.1)
├── sails-disk#0.9.3 (waterline-criteria#0.9.7, lodash#2.3.0, fs-extra#0.8.1)
├── fs-extra#0.5.0 (jsonfile#0.0.1, ncp#0.2.7, mkdirp#0.3.5, rimraf#2.1.4)
├── connect-redis#1.4.5 (debug#0.8.0, redis#0.7.3)
├── grunt-contrib-jst#0.5.0 (lodash#1.0.1, grunt-lib-contrib#0.5.3)
├── glob#3.1.14 (inherits#1.0.0, graceful-fs#1.1.14, minimatch#0.2.14)
├── grunt-contrib-cssmin#0.6.1 (grunt-lib-contrib#0.6.1, clean-css#1.0.12)
├── grunt-cli#0.1.9 (resolve#0.3.1, nopt#1.0.10, findup-sync#0.1.3)
├── grunt-contrib-watch#0.4.4 (gaze#0.3.4, tiny-lr#0.0.4)
├── connect-mongo#0.3.2 (mongodb#1.2.14)
├── grunt-contrib-uglify#0.2.2 (grunt-lib-contrib#0.6.1, uglify-js#2.3.6)
├── waterline#0.9.16 (underscore#1.5.2, q#0.9.7, anchor#0.9.12)
├── grunt#0.4.1 (which#1.0.5, dateformat#1.0.2-1.2.3, eventemitter2#0.4.13, colors#0.6.2, hooker#0.2.3, async#0.1.22, nopt#1.0.10, minimatch#0.2.14, lodash#0.9.2, rimraf#2.0.3, coffee-script#1.3.3, underscore.string#2.2.1, iconv-lite#0.2.11, glob#3.1.21, findup-sync#0.1.3, js-yaml#2.0.5)
├── winston#0.7.1 (cycle#1.0.3, stack-trace#0.0.9, eyes#0.1.8, colors#0.6.2, pkginfo#0.3.0, request#2.16.6)
├── express#3.4.0 (methods#0.0.1, debug#0.8.0, range-parser#0.0.4, cookie-signature#1.0.1, fresh#0.2.0, buffer-crc32#0.2.1, cookie#0.1.0, mkdirp#0.3.5, commander#1.2.0, send#0.1.4, connect#2.9.0)
├── grunt-contrib-less#0.9.0 (grunt-lib-contrib#0.6.1, chalk#0.4.0, less#1.6.3)
└── socket.io#0.9.14 (base64id#0.1.0, policyfile#0.0.4, redis#0.7.3, socket.io-client#0.9.11)
The problem is when you try to use sails: you run sails new project, for example, and it doesn't find sails. Investigating a little bit, I discovered npm is not installing the modules at /usr/bin. Is there some reason for that? Some config?
The same is happening with Karma module.
I used the nodejs from ppa, created the symbolic link for node and installed npm from the official install.sh script (https://www.npmjs.org/install.sh).
It sounds like your npm installation is configured to use /home/brunoluiz/npm as prefix, meaning that it will place symlinks to the CLIs that come with globally installed packages in {prefix}/bin.
In a default installation, prefix is either /usr or /usr/local on Unix platforms (%APPDATA%/npm on Windows).
If {prefix}/bin is not in your $PATH, you won't be able to execute such CLIs just by name.
To see the current prefix value in effect, run:
npm get prefix
Your options are:
Add /home/brunoluiz/npm/bin to your $PATH
Change the value of the prefix configuration item to a folder whose bin subfolder is already in your $PATH; e.g.:
npm set prefix /usr # Ubuntu; CLI symlinks are placed in /usr/bin
npm set prefix /usr/local # OSX; CLIs symlinks are placed in /usr/local/bin
Note, however, that you'd then have to reinstall your global packages for the symlinks to be created in the new {prefix}\bin location.
In addition to mklement0's answer, the first solution (adding the npm binary directory path to the PATH variable) creates another problem when the commands are run with sudo prefix on Linux environment. To solve it, the npm binary directory path must also be added in secure_path in /etc/sudoers.tmp. Here is how:
Why can't sudo find a command after I added it to PATH?

Resources