I installed globally eslint#4.2.0 and wanted to use some predefined configs. When I tried to install eslint-config-google it said that I don't have eslint>=4.1.0 (which I had of course, but installed globaly). The same problem occured when installing eslint-config-airbnb-base - ultimately predefined configs can't see globally installed eslint (and even eslint --init can't see it cause it installed another instance of eslint locally when I run it). Then I decided to install both eslint and configuration files locally, in my projects directory - works like a charm, but still I'd like to have these things in global scope so I wouldn't have to care about it each time I make a new directory for my projects.
Is it possible to make eslint and predifined configs work at global scope or at least have global eslint and local configuration file?
ultimately predefined configs can't see globally installed eslint
Actually, they can. Or rather, global ESLint can use global configs. It just doesn't know how to cross the barrier between global and local.
Then I decided to install both eslint and configuration files locally, in my projects directory - works like a charm
Good choice. This is going to be crucial when you eventually have projects with conflicting needs.
but still I'd like to have these things in global scope so I wouldn't have to care about it each time I make a new directory for my projects
That is what project scaffolding tools like Yeoman are for. Here is the one I use, generator-seth.
Whenever I start a new project, I simply type seth and answer a couple of questions and it's done with glorious magic under the hood.
Is it possible to make eslint and predifined configs work at global scope or at least have global eslint and local configuration file?
Yepp. You can have a local .eslintrc file and the global ESLint will respect it. You can run eslint --init to set this up (that will also install ESLint locally, but you don't need to use it).
But an even better way is to use XO, which is built on top of ESLint (and supports all ESLint rules). Unlike ESLint, XO knows how to automatically choose the appropriate installation to use. You can install it both locally and globally and its global CLI will defer to the local copy when one is detected. This is important because it means that each project can keep its own version of the linter while still allowing you to run XO globally. So if a breaking change comes out, your projects are not screwed all at once or broken when they have conflicting needs. The configuration for XO is kept locally either way, so unlike ESLint you do not have duplicate local and global configs.
I have recently encountered the same issue, here is my solution (OS: Windows):
First, I run eslint initial command to configure my preference:
$ eslint --init
? How would you like to use ESLint? To check syntax, find problems, and enforce code style
? What type of modules does your project use? CommonJS (require/exports)
? Which framework does your project use? None of these
? Where does your code run? Browser, Node
? How would you like to define a style for your project? Use a popular style guide
? Which style guide do you want to follow? Airbnb (https://github.com/airbnb/javascript)
? What format do you want your config file to be in? JavaScript
Checking peerDependencies of eslint-config-airbnb-base#latest
The config that you've selected requires the following dependencies:
eslint-config-airbnb-base#latest eslint#^4.19.1 || ^5.3.0 eslint-plugin-import#^2.17.2
? Would you like to install them now with npm? No
Second, I copy the ".eslintrc.js" file that eslint generated locally into my user home directory (C:\Users\username) to make it a global configuration file.
Finally, I use npm to install the required packages globally:
npm install -g eslint#^5.16.0 eslint-config-airbnb-base eslint-plugin-import
*Important*
Don't use npm install -g eslint because it will install the latest eslint version
(like 6.0.1) and therefore, the dependencies of eslint-config-airbnb-base and eslint-plugin-import will go wrong
And here is the article you may find more information if you want configure differently How to globally set up eslint in vscode.
Related
I just recently heard of the package.json file but all my small projects have always worked without it.
I've installed many npm modules globally and always use var x = require("express");"just for example" without even initializing the package.json and putting express as a dependency.
Is it really important
First of all, I strongly doubt require("express") will work out of the box without having the express package installed in your project's node_modules folder, but just globally. There are ways to accomplish this, though.
But even if you accomplished to require packages from the global installation folder, what happens if you have multiple packages requiring different versions of the same package? There may be breaking changes between major versions of packages. So if you install a new version of package xy globally, older projects of yours expecting a different version of package xy may stop working.
On just your local machine, you can achieve all that, still without a package.json though.
The main purpose of the package.json comes clear, when you want to share your project with other people. Aside from some basic information (like a package name and some description), it will also list the dependencies which need to be installed for the project to be runable. While the necessary dependencies may exist on your machine, how will you make sure, they are also installed on a different machine without having them listed somewhere? And the place for listing the dependencies of a package is -- surprise surprise --- the package.json file ...
They are global, not in your project so when you do the deploy, you will must have to install all global for each server.
Yuu can install packages-cli global, but project dependencies ( also dev on dev dependencies) is better have its own package.json so you can deploy.
Also if you share your project, how someone will know what packages is needed.
The better is to have for each project its own package.json on its root folder, even if you always use the same libs.
I'm developing a web app which uses a private package.
In some circumstances, I rather to use the local version of the package or different version of that package.
Is there any solution to indicate to use different version of package in package.json?
i.e:
npm install --local
while my package.json looks like:
...
"dependencies": {
...
"my_package": if(local) "address_to_local_package/" else "5.6.1"
...
}
npm does not accommodate this (and honestly, probably should not). This seems like the type of thing that is usually handled at runtime via the NODE_ENV environment variable or similar mechanism. The module changes behavior depending on whether NODE_ENV is set to "production" or "development". (But that's just convention. You can use values like "local" if you want.) So rather than installing different versions of the module, there's a single version that behaves differently based on the value of that environment variable.
If you really want different code bases installed entirely, it will take some effort but you can write a postinstall script for npm to run. Your module then becomes nothing more than a script and then the postinstall figures out what to actually install based on environment variables or maybe a command line flag. This seems brittle to me, though. I'd think hard about if you're solving the right problem here if you go this route. NODE_ENV seems more elegant and conventional.
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.
Let's say I've already published a nodejs module on npm. It's simple, you install and import it, and given a string and a config object it returns a string.
Now, I wanted to make it available both as local and global module: I added a script to bin in package.json. The script imports and uses the local function and prints the result. To handle the argument and the config object I used npm yarg as a dependency.
The problem is this: if I want to install my module as local, the yarg dependency is not needed, because it is used only when the module is used as global. So it's a waste of space.
Is there a way to make the yarg dependency be installed only when my module is installed as global module and not local?
This is not a common practice by any means. There can be scenarios when a package installed locally can be usable as CLI executable, notably as a part of NPM script. All popular packages that are supposed to be used globally like npm or grunt can also be installed and run locally.
There is no reliable way to detect that a package was installed globally. This can be potentially done by detecting that a module resides in node_modules global location. There may be caveats that depend on specific system.
The footprint of yargs is 760 Kb, which is not crucial. If the footprint of CLI-specific functionality is considerable, CLI executable can be extracted to separate package that depends on original package.
2 manuals about gulp say that I need to install gulp first globally (with -g flag) and then one more time locally. Why do I need this?
When installing a tool globally it's to be used by a user as a command line utility anywhere, including outside of node projects. Global installs for a node project are bad because they make deployment more difficult.
npm 5.2+
The npx utility bundled with npm 5.2 solves this problem. With it you can invoke locally installed utilities like globally installed utilities (but you must begin the command with npx). For example, if you want to invoke a locally installed eslint, you can do:
npx eslint .
npm < 5.2
When used in a script field of your package.json, npm searches node_modules for the tool as well as globally installed modules, so the local install is sufficient.
So, if you are happy with (in your package.json):
"devDependencies": {
"gulp": "3.5.2"
}
"scripts": {
"test": "gulp test"
}
etc. and running with npm run test then you shouldn't need the global install at all.
Both methods are useful for getting people set up with your project since sudo isn't needed. It also means that gulp will be updated when the version is bumped in the package.json, so everyone will be using the same version of gulp when developing with your project.
Addendum:
It appears that gulp has some unusual behaviour when used globally. When used as a global install, gulp looks for a locally installed gulp to pass control to. Therefore a gulp global install requires a gulp local install to work. The answer above still stands though. Local installs are always preferable to global installs.
TLDR; Here's why:
The reason this works is because gulp tries to run your gulpfile.js using your locally installed version of gulp, see here. Hence the reason for a global and local install of gulp.
Essentially, when you install gulp locally the script isn't in your PATH and so you can't just type gulp and expect the shell to find the command. By installing it globally the gulp script gets into your PATH because the global node/bin/ directory is most likely on your path.
To respect your local dependencies though, gulp will use your locally installed version of itself to run the gulpfile.js.
You can link the globally installed gulp locally with
npm link gulp
The question "Why do we need to install gulp globally and locally?" can be broken down into the following two questions:
Why do I need to install gulp locally if I've already installed it globally?
Why do I need to install gulp globally if I've already installed it locally?
Several others have provided excellent answers to theses questions in isolation, but I thought it would be beneficial to consolidate the information in a unified answer.
Why do I need to install gulp locally if I've already installed it globally?
The rationale for installing gulp locally is comprised of several reasons:
Including the dependencies of your project locally ensures the version of gulp (or other dependencies) used is the originally intended version.
Node doesn't consider global modules by default when using require() (which you need to include gulp within your script). Ultimately, this is because the path to the global modules isn't added to NODE_PATH by default.
According to the Node development team, local modules load faster. I can't say why this is, but this would seem to be more relevant to node's use in production (i.e. run-time dependencies) than in development (i.e. dev dependencies). I suppose this is a legitimate reason as some may care about whatever minor speed advantage is gained loading local vs. global modules, but feel free to raise your eyebrow at this reason.
Why do I need to install gulp globally if I've already installed it locally?
The rationale for installing gulp globally is really just the convenience of having the gulp executable automatically found within your system path.
To avoid installing locally you can use npm link [package], but the link command as well as the install --global command doesn't seem to support the --save-dev option which means there doesn't appear to be an easy way to install gulp globally and then easily add whatever version that is to your local package.json file.
Ultimately, I believe it makes more sense to have the option of using global modules to avoid having to duplicate the installation of common tools across all your projects, especially in the case of development tools such as grunt, gulp, jshint, etc. Unfortunately it seems you end up fighting the tools a bit when you go against the grain.
Technically you don't need to install it globally if the node_modules folder in your local installation is in your PATH. Generally this isn't a good idea.
Alternatively if npm test references gulp then you can just type npm test and it'll run the local gulp.
I've never installed gulp globally -- I think it's bad form.
I'm not sure if our problem was directly related with installing gulp only locally. But we had to install a bunch of dependencies ourself. This lead to a "huge" package.json and we are not sure if it is really a great idea to install gulp only locally. We had to do so because of our build environment. But I wouldn't recommend installing gulp not globally if it isn't absolutely necessary. We faced similar problems as described in the following blog-post
None of these problems arise for any of our developers on their local machines because they all installed gulp globally. On the build system we had the described problems. If someone is interested I could dive deeper into this issue. But right now I just wanted to mention that it isn't an easy path to install gulp only locally.
Just because I haven't seen it here, if you are on MacOS or Linux, I suggest you add this to your PATH (in your bashrc etc):
node_modules/.bin
With this relative path entry, if you are sitting in the root folder of any node project, you can run any command line tool (eslint, gulp, etc. etc.) without worrying about "global installs" or npm run etc.
Once I did this, I've never installed a module globally.