Bower's documentation section on "Consuming a package" says:
Bower also makes available a source mapping. This can be used by build tools to easily consume Bower packages.
Then it exemplifies the JSON that you can output with a simple command:
{
"backbone": "bower_components/backbone/index.js",
"jquery": "bower_components/jquery/index.js",
"underscore": "bower_components/underscore/index.js"
}
I understand what's going on here ... but I don't really understand what it's for, i.e. how to use it.
I haven't been able to find examples of people using such a source map, and it's not easily apparent to me what the Bower docs are suggesting. I'm wondering how this Bower-generated JSON can be used by build tools to consume packages, easily.
Does anybody know? Has anybody done this or seen it done?
One of the main uses (at least as far as I know) for using the list --paths option and seeing the mapping is for build tools - as the docs suggest. It'd be good if they gave an example, but I can here.
So say you're using Bower to manage front-end dependencies but you're using Grunt to build your site/app. How do you reconcile the two? Bower installs dependencies in a default root like 'app/_bower_components/packageName/' ie a path you'd never want to use in production or probably even development because its awkward and may refer to an un-minified version of the package/library JS.
Grunt has tasks like 'uglify' that take a given JS file and minify and mangle it down to a much smaller size, useful for production sites. In Grunt you might write a task like this:
uglify: {
modernizr: {
files: {
'javascripts/modernizr.min.js': 'app/_bower_components/modernizr/modernizr.js'
}
}
This uses the mapping Bower provided in the second argument (ie points to the Bower source) and outputs the uglified output to the first argument (in this case javascripts/modernizr.min.js) for production purposes.
In this sense your build tool, Grunt, 'consumes' your Bower packages and copies & minifys them for your site. This way as long as your Uglify task has the right path, you can use Bower to update/manage your dependencies and you wont directly edit the source. So if for instance there's a new version of JQuery you just update it via Bower and shouldn't need to do anything else; no manual copying, no editing.
Related
This must be a commonly solved problem, but I cannot find a whole lot on Google/SO so far.
When we run npm install and fetch say 50+ packages including devDependencies as well as runtime dependencies, npm creates node_modules (if needed) and adds each of those packages inside that folder. This means we end up with thousands of extraneous files included under node_modules. Each of those packages contains their own package.json, README.md, minified files, source files, etc. Our application really only cares about jquery.js (for DEV) and jquery.min.js (for PROD), so it seems to be a waste to include all of these other files into our build and therefore our web server.
Is there a standard when it comes to handle these npm packages in a way so that we simply expose ONLY the necessary files to the user? I imagine many people have this kind of issue but I don't see any built in npm constructs that allow us to do this easily.
See below.. the yellow highlighted files are the only files we really care about in Production, but we get all these extra files as well including the source code.
The most common solution consist of bundling your application on a different machine and then expose the built artefacts on production server.
There are a lot of great JS bundlers out there. The ones I have personally used are Browserify, Webpack, and Rollup. All amazing tools.
The main idea consists of writing your application in a Node environment and then bundle it to make it readable to the browser.
For simpler projects I find Browserify a very good compromise between power and ease of configuration. But it's a matter of taste, at the end. :)
Base on what I read about npm install documentation I do not think there is a option to manipulate the installation in the way you want. The packages will install the way the package author decides to package it, sometimes minified sometimes not.
Having said that, you should look for third party solutions like modclean which does exactly what you want post package installation. Run this command in the root of your project directory
npm install modclean -g
modclean
As long as your test coverage is good, ModClean would be perfect for your need.
Edit the package.json file and remove all the unnecessary dependencies then do
npm install --save
By doing this, it will create a local node_modules folder and only download the necessary packages into it (not the global node_modules folder)
Keep in mind, by default, node checks for local node_modules folder. If it couldn't find it, it will use the global folder.
Also, you don't expose all the packages in the node_modules folder. In fact, they will not be used unless you require(); them in the node.js file
EDIT:
For jQuery to work in Node, a window with a document is required. Since no such window exists natively in Node, one can be mocked by tools such as jsdom. This can be useful for testing purposes. https://www.npmjs.com/package/jquery
require("jsdom").env("", function(err, window) {
if (err) {
console.error(err);
return;
}
var $ = require("jquery")(window);
});
So jquery module do things a bit differently behind the scene for node.js comparing to the regular front-end jquery.
It requires jsdom so you will have to download that as well from here https://github.com/tmpvar/jsdom
I've been playing around with webpack and npm registry. I created my own little project. which I published to npm registry. Everything seems to work fine, but there is one thing that worries me.
The file which is built by webpack (lib/index.js) contains almost 2k lines of code while my library is really tiny. I see that it includes two dependencies that I use which are prop-types and detect-browser. They make most of the code.
Hover after downloading these two libraries and using them in a test project I would expect them to be somehow deduped by tree-shaking or something like that, but the size of my package is still the same.
Basically, all I'm asking is: does my library includes more code than necessary? It seems like so to me.
I also tried to additionally install prop-types and detect-browser in the test project to see if bundle size will remain the same. Hower the size of my library is still the same and bundle size increased (I expected that redundant libraries will be removed or something).
How did you generate the dependency graph?
BTW your package looks fine except for the fact that your are including in you distributed code both the packages you are depending on (prop-types and detect-browser).
In order to avoid that you should mark as external those libraries in your webpack config file. Like:
externals: {
react: 'react',
prop-types: 'prop-types',
detect-browser: 'detect-browser',
}
Just a final (personal) note: give Rollup a try to bundle your libraries. :)
I have gotten better at using the command line. I now use it regularly for foundation, gulp, ionic, etc. One thing I always struggle with is should I be installing modules globally?
I just got a new computer and I am starting fresh. When I do my first Foundation Project, or set up Gulp, when it prompts me to run 'npm install' should I be installing that gloabally? And if I do, will I need to run npm install the next time I set up a Foundation Project?
I think that NPMs documentation really sums it up quite nicely:
If you want to use it as a command line tool, something like the grunt CLI, then you want to install it globally. On the other hand, if you want to depend on the package from your own module using something like Node's require, then you want to install locally.
https://docs.npmjs.com/getting-started/installing-npm-packages-globally
In this case, you should install locally since they are dependencies of the application and not general command line utilities.
This doesn’t fit the Q&A format too well, but I would in general advise against that. Installing modules globally may lead to side effects in other projects that depend on the same packages.
I don’t know what a “Foundation Project” is (and Google does not yield a clear answer), so I think you’d have to add a link explaining what that is.
Can we manage dependencies (js/css), minify, build, serve, watch ... only with node and nmp. If so how it works and why people use grunt, gulp, bower with npm ?
Basically on what i understand (angular-cli is very recent) it hide the webpack .. in reality it use it behind the scene ... i prefer to use the stack made by myself with Webpack and npm .. but now they've just released a new feature the AOT compiler.
https://angular.io/docs/ts/latest/cookbook/aot-compiler.html
In reallity it is possible to be done also with webpack .. but you need some changes of your code :
https://github.com/blacksonic/angular2-aot-webpack
Angular-cli is taken (as idea) from Ember-cli .. it help you to manage and create (scaffold) your app....
I think (but it's my idea) I'll continue without it and I'll try to implement new features (as AOT) by myself cause i want to know what happen behind the scene and know everything of my stack.... but it's my personal idea
Hope it help you ..
Can we manage dependencies (js/css), minify, build, serve, watch ... only with node and npm.
the "pm" in "npm" stands for "package-manager" so, of course you can use it as your main package manager.
You can define your own npm scripts in the package.json file and they'll get run when you enter arbitrary command in the console (npm run {script-name}). It can - in some way - replace grunt, gulp and other task-runners.
why people use grunt, gulp, bower with npm ?
Good question, in fact it's like using a framework, when using gulp, grunt, etc, you have a single API, and you can easily find ready-made tools that fit your needs and save your time instead of writing your own script every time.
Using these tools also allow to use a unified API to run all your tasks and avoid you messing with several scripts, and question such as "how should I pass arguments to this script ?" "what is the command to run this ?" etc.
For bower vs npm there is already an answer here
I've converted to npm for my build system: no gulp etc. Also no webpack, rollup etc, it's an es6 system based on modules & no bundling. Sure is simple!
Obviously I don't want to drag around a node_modules hierarchy for my run-time, front end modules. And don't want to import foo from './node_modules/god/awful/path.js'. So I'd like to have a top level directory for the run-time, front-end dependencies.
So how do I copy my "dependencies", not "devDependencies", to a top level directory for deployment?
I've got a run script that can do it but it's pretty messy and the location of the package under node_modules is not always obvious. Maybe there's a package for doing this automatically? Or a nifty npm trick of some sort?
OK, I'm starting to need this even more than before so thought I'd nag and be clearer about what I seem to be forced to do.
First of all, I use no workflow task managers, just npm run scripts in package.json.
My dependencies (npm --save .. not --save-dev) are:
"dependencies": {
"lzma": "^2.3.0",
"pako": "^1.0.0",
"three": "*"
},
.. and my scripts cli for hoisting the dependencies into a top level libs/ dir is simply a huge cp:
"build-deps": "cp
node_modules/lzma/src/lzma.js
node_modules/lzma/src/lzma_worker.js
node_modules/pako/dist/pako.min.js
node_modules/three/build/three.js
node_modules/three/build/three.min.js
node_modules/three/examples/js/controls/OrbitControls.js
node_modules/three/examples/js/controls/FlyControls.js
node_modules/three/examples/js/controls/FirstPersonControls.js
node_modules/three/examples/js/libs/stats.min.js
node_modules/three/examples/js/libs/dat.gui.min.js
libs/",
This is pretty primitive: I have to find the dependencies in node_modules (not always obvious) and add them to the list by hand. Sure makes me want fewer dependencies! :)
I know that bower is designed for "front end" dependencies (--save in npm speak). But it seems like npm would be perfect for dependencies, and yet it appears I need to be this primitive.
What am I missing here? What do you do?
This is something I wrestled with in my earliest forays into development with Node packages. I had the exact same idea you had: "I can use npm to pull in whatever I need for my project, great!" and then trying to manage how I reference each of my dependent libraries. I didn't properly grasp at the time that npm wasn't just there to help me fetch my dependencies, it's also there to help me manage them.
Here's the long & short of it: you do NOT want to be copying anything out of your node_modules folder to some other, more human-convenient location. There's a lot of reasons why, but the biggest is that you don't need to copy anything out of node_modules -- everything your project needs is right there.
When you're developing in ECMAScript 2015+ you should only ever have to do the following (apologies for the overly-simplistic code):
/* N.B. These all reside under node_modules, yet I don't
* have to spell out their paths under node_modules: */
import $ from 'jquery';
import _ from 'lodash';
import moment from 'moment';
import NiftyLibrary from 'niftywhatever';
// ... code ...
let $name = $('#name');
let now = moment();
// ... other code ...
In other words, your development environment setup should just handle the module resolution for you. You should never have to specify that the jQuery library you want to use is at "node_modules/jquery/dist/jquery.min.js". If you're doing this you should take a minute to figure out why you're doing this -- it's unnecessary, it's a time- and brain-suck and you'd rather be writing your application code than managing your dependencies ... NOT managing the node_modules tree.
You mentioned you're developing with ES6 modules, but not using webpack, gulp, Grunt, rollup or any other build or bundling tool. Is your project intended to run entirely in Node? I ask because the last I heard most browsers aren't quite ready to run ES6 modules natively. So how are your modules getting transpiled to ES5? Maybe you're approaching this in some novel way I haven't heard of yet, but in my experience a build or bundling tool is necessary. (Also, it's a heck of a lot of fun.)
I've used Grunt with RequireJS in the past, but am now using webpack 3 with Babel and a few additional loaders (depending on the type of project I'm working on). I use npm scripts to handle my top-level tasks (running a development server, building a finished distribution package, running tests, etc.), but I let webpack handle all the business of transpiling ES6 into ES5, translating Sass styles, precompiling Vue components, etc. It's a bit of work to wrap your mind around the webpack approach, but it's well worth the effort.
Maybe webpack doesn't fit your style -- fair enough. But there are a number of other tools you could use instead. They all require a little time to get acclimated to their approaches, but they should all be able to take care of module resolution for your dependencies. Once you get a build environment set up correctly it should cease being a visible part of your development workflow; you'll just reference your dependent libraries by their names, map them to a module-local variable and use them.
Is this helpful?
EDIT: This is webpack-specific, but there should be similar options available with other bundlers or build tools.
In webpack you can use the copy-webpack-plugin to copy npm-sourced dependencies to a separate folder. This can be useful within a service worker, for example, where the execution context is a little different.
What I would suggest is scoping your dependencies (#frontend/...) and symlinking the scoped folder to your top-level dir in a post install script (similar to how bower handled the transition to yarn: see https://github.com/sheerun/bower-away)
Example:
...
"dependencies": {
"#frontend/jquery": "npm:jquery#~3.4.1",
},
"engines": {
"npm": ">=6.9.0",
"node": ">=12.10.0"
},
"scripts": {
"postinstall": "node -e \"try { require('fs').symlinkSync(require('path').resolve('node_modules/#frontend'), 'static/bower', 'junction') } catch (e) { }\""
}
Requires NPM >= 6.9 for alias support.
FYI: aliases break audits