I'm looking at some code from a coworker wrote and she's using the @
symbol in require statements. This is the first line of one of these files:
var restServer = require('@company/config')
When I try to run this code, I get an error:
Error: Cannot find module '@company/config'
Which I frankly expect, there's nothing that looks like this in my directory for require to recognize! It seems like there's some magic going on here, which I hate.
All I can guess is that either this is some obscure npm or Node trick that I haven't been exposed to, or maybe that there's some other dark art of configuration that I'm not getting. Any info appreciated, even if it's just an explanation of how @
works with require.
Other ideas: Chef is involved somewhere in this whole thing, so that might be relevant.
Update: 99% certain this is an issue with the way npm config
works at this point, but still unsure of how to go about fixing it.
Update2 based on some stuff I uncovered:
Dereks-MacBook-Pro:project-dir derekjanni$ npm config set //registry.npmjs.org/:authtoken $SECRET_TOKEN
Dereks-MacBook-Pro:project-dir derekjanni$ npm install
npm ERR! Darwin 15.0.0
npm ERR! argv "/usr/local/Cellar/node/5.5.0/bin/node" "/usr/local/bin/npm" "install"
npm ERR! node v5.5.0
npm ERR! npm v3.5.3
npm ERR! code E404
npm ERR! 404 Not found : @company/config
npm ERR! 404 '@company/config' is not in the npm registry.
Scoped packages in npm are preceded by an '@' symbol: https://docs.npmjs.com/misc/scope
The docs include additional information on requiring scoped packages: https://docs.npmjs.com/misc/scope#requiring-scoped-packages
Requiring scoped packages
Because scoped packages are installed into a scope folder, you have to include the name of the scope when requiring them in your code, e.g.
require('@myorg/mypackage')
There is nothing special about the way Node treats scope folders, this is just specifying to require the module mypackage in the folder called @myorg.
So I solved this one myself.
Turns out @company/config
is one of our private NPM repositories, hosted on npm and defined by this alias to an internal GitHub repository: it had nothing to do with how require
works.
Using @
may or may not be a protocol that I was unaware of for private NPM repos, keep that in mind if you run into this.
The @
scope is indicates package ownership
From the official documentation is at: https://docs.npmjs.com/about-scopes
When you sign up for an npm user account or create an Org, you are granted a scope that matches your user or Org name. You can use this scope as a namespace for related packages.
A scope allows you to create a package with the same name as a package created by another user or Org without conflict.
The main advantage of scopes I've seen so far is that each scope is controlled by npm account of an organization / user, much like GitHub usernames / organization names.
This way, it makes it easy to determine if the package you are looking at belongs to an organization you trust, or if it is a third party tool.
For example, if you see a package:
@angular/cli
then you know that it comes from the user / group that controls the Angular team and can be trusted.
On the other hand, the same could not be said about:
angular-cli
TODO: the web UI / URL scheme is really wonky, how do you easily link: https://www.npmjs.com/package/@angular/cli to the corresponding organization / user page, presumably https://www.npmjs.com/~angular ? By searching the page source, the only hit for that URL is under "collaborators", but that contains other collaborators as well: https://www.npmjs.com/~angular-cli and https://www.npmjs.com/~google-wombot
See also: What is the meaning of the "at" (@) prefix on npm packages?
Apart from scoped packages, the '@' can arise due to module-alias package in npm. Through module aliasing you can use frequently used modules without requiring its entire path. Also its effective when directory structure is long. e.g.) require('../../../../some/very/deep/module')
Instead you can use: var module = require('@deep/module')
In package.json you can provide the modules for which you are providing alias:
"_moduleAliases": {
"@root" : ".", // Application's root
"@deep" : "src/some/very/deep/directory/or/file",
"@my_module" : "lib/some-file.js",
"something" : "src/foo", // Or without @. Actually, it could be any string
}
And in the main file of the app use this:
require('module-alias/register');
Refer here for detailed info: module-alias
When you call require()
it reads a route. Since there seems to be no problem if you name a folder as @company
, you should be able to require something with an @
.
Your coworker may have wanted to keep @company/config.js
for herself because configurations usually are personal and could not be the same for another user.
require
will call files inside your project folder, with a detail:
./
in front of your route. http
or any npm
modules (which are installed at node_modules
), you can omit the ./
.I created a route @company/config
inside my test project folder. It only allowed me to require it using ./@company/config
. Only when i moved the folder inside node_modules
, it allowed me to require('@company/config');
.
I wouldn't recommend to put any module inside node_modules
, it's just a 'container' for npm
packages. Try to create a new config file and change the require route or simply delete the require and create a config object in your main file.
©2020 All rights reserved.