Fallback for webpack external libraries - angularjs

Is there a way to specify a fallback for webpack external, for example if I can't find angular then try to search for it in your node_modules?

You can reference parts 2 of the answer to this Webpack question.
You can use the provide plugin and set an alias for the global. As stated:
Most legacy modules rely on the presence of specific globals, like jQuery plugins do on $ or jQuery. In this scenario you can configure webpack, to prepend var $ = require("jquery") everytime it encounters the global $ identifier.
The angular global will be treated the same way. Therefore if you don't have angular in node modules but loaded via external script, Webpack will allow you to use it the same way as if it was living in your node modules.

Related

Using webpack with angular.1.5 , php and bower

my index.php is like the following :
<script src="app/bower_components/jquery/dist/jquery.min.js"></script>
<script src="app/bower_components/angular/angular.min.js"></script>
<script src="app/bower_components/angular-ui-router/release/angular-ui-router.min.js"></script>
<script src="app/bower_components/angular-sanitize/angular-sanitize.min.js"></script>
I would like to add webpack to bundle all these files and minify them
I did not find the way to do that.
I have installed npm , node and webpack
I manged to us webpack to simple files like: webpack entry.js bundle.js . but not for my angular app
Let me answer it in general and then specific to your use case.
IN GENERAL:
Webpack
is a module bundler
needs entry and output as minimum
configuration
Where do i configure/list-out all my application code?
You dont configure it but code it. Please read on...
How webpack knows what code/modules to pick up to bundle?
Webpack will look at the code configured for entry and then internally builds its module dependencies (as dependency graph).
How do you declare module dependencies?
In short: by using require("module-or-path-here") or import "module-or-path-here". Do note that the javascript (ES6 a.k.a ES2015) itself has native module support now. Here is a good article on JS modules.
What is dependency graph?
Webpack will start with the code configured for entry and then pick up its immediate dependencies. It then goes to find out the dependencies of those immediate dependencies and so on...
Once the dependency graph is complete, webpack will start processing them and bundle them into output.filename located at output.path
Fine, but i want to perform some resource (JS / CSS / SCSS / images, etc..) specific work for ex. minify js code. How to do that?
Webpack is flexible (and powerful) and allows to configure resource specific work via loaders and plugins.
IN SPECIFIC:
The modules in AngularJS (i.e. 1.x) are not same as the modules that webpack works with. As you can see, while declaring the modules in angularJS, you are defining modules with angular by calling angular.module.
One option is to make sure to bundle all your angular module definition files (i.e that consists of angular.module("module-name-here", ["depenndencies"])) first followed by the angular components that needs those modules. There are several way to do that. For ex. name all your angular modules declaration files with a common pattern and then configure webpack to pick them up first.
Minification is pretty simple to achieve with webpack. You can try one of the options pointed out in the webpack documentation.

Where is the variable named "global" coming from

I am refactoring a React 15 application (built with Webpack 2 and Babel) and I have noticed a lot of references to a global variable called global e.g. global.location. It's an alias for window, but I cannot find any code or configuration where the assignment occurs.
The Chrome devtools console can't access global so it is contained inside the modules that webpack generates. It's a very overloaded search term and I haven't had any luck tracking it down on Google.
Where is global coming from? Is there any benefit using it in a web application over window?
The global variable is handled specially by Webpack, not by Babel. Webpack's configuration file may contain a node section, which controls the polyfilling of various node objects, like global. Unless otherwise specified, global will be rewritten by webpack to mean window.
Example webpack.config.js turning off global rewriting:
module.exports = {
node: {
global: false
}
}
Documentation from project wiki.

Webpack external attribute meaning

I'm reading a react project. In this project, they defined an external like this:
webpackConfig.externals = {}
webpackConfig.externals['react/lib/ExecutionEnvironment'] = true
webpackConfig.externals['react/lib/ReactContext'] = true
webpackConfig.externals['react/addons'] = true
I have read Webpack document but I still don't understand above lines. What is the meaning when define those configurations ?
Thanks
The externals configuration option provides a way of excluding dependencies from the output bundles. Instead, the created bundle relies on that dependency to be present in the consumer's environment. This feature is typically most useful to library developers, however there are a variety of applications for it.
It is used to build a library with webpack that has dependencies to other libraries which should not be included in the compiled version. The externals option defines dependencies that should be resolved in the target environment.
Check these links for more explanation:
https://webpack.js.org/configuration/externals/
https://github.com/webpack/webpack/tree/master/examples/externals
http://tomasalabes.me/blog/_site/web-development/2016/04/30/Webpack-Series-Part-1.html

How to package an angular module with translations so it can be reused

How can you package an angular module with its own translations stored in json files, without harming or needing extra config from the host app? This module should be able to exist as a bower dependency.
Basically I want the templates (directives) in my module to set the correct values, based on the $translate.use() of the main (ng-app) module. This without any concatenating of files or special config required by the main app. This would allow me to quickly add the module to various applications. You would just include the module in your app config angular.module('my-app', ['my-translated-module]); and it would be able to render the translations correctly as soon as you're starting to use the directive. The config of the translation is of course in the config section of 'my-translated-module'
For example: think of a login form with a "sign up" and "login" button. I want to have it this as a separate module/directive, so different applications could reuse that part, without having the duplicate the translations. If the module gets an update, i just need to do a bower update on my main app, rerun
I'm on angular 1.5 and using the angular-translate library by pascal precht - with the static file loader.

What's the use of exports / module.exports?

Today I've adopting Browserify for my AngularJS project, but there is something that's very unclear to me. In all examples and blog posts I've seen stuff like this:
/app.js:
require('./messages');
angular.module('sling', ['sling.messages']);
/messages/index.js:
exports = angular.module('sling.messages', [])
.controller('MessagesListCtrl', require('./MessagesListCtrl'));
/messages/MessagesListCtrl.js:
module.exports = function() {
// ...
});
Sure, this works, but why do this? I've implemented it like this and that works absolutely fine too and feels more normal for an AngularJS project:
/app.js:
require('./messages');
angular.module('sling', ['sling.messages']);
/messages/index.js:
angular.module('sling.messages', []);
require('./MessagesListCtrl');
/messages/MessagesListCtrl.js:
angular.module('sling.messages').controller('MessagesListCtrl', function() {
// ...
});
In other words, I'm completely skipping the exports/module.exports, only using require to basically include the files with the controllers, services, filter, etc.
Am I doing this right? I mean it all works, but am I going to be in trouble later on?
The main (and honestly only) reason to use Browserify is if you want to have CommonJS modules (i.e. NodeJS modules) in the browser. A CommonJS module stays out of the global scope by having an implicit 'module' scope. You choose what to expose from the module scope (usually the entry point or primary function of your module) into by augmenting the 'exports' object that every module has.
So a 'real' CommonJS module looks like this.
File A:
// a.js
function doSomething() {
console.log("I am doing something");
}
module.exports = doSomething
File B:
// b.js
doSomething();
// Exception - attempt to call a non-existent function
File C:
// c.js
var doSomething = require('a');
doSomething();
// logs "I am doing something"
In the browser which has no module scope, a.js would be augmenting the global scope with the doSomething function, since it's declared as a global. Browserify works around this by wrapping each bundled module into a function wrapper, and supplying an 'exports' object to the included modules as an argument to this wrapper.
Enter AngularJS. You've got two approaches you can use here, of which I'm assuming from the fact that you're not using require('angular') is the first:
Include AngularJS as a hard-coded script available in your index.html before your Browserify-transpiled bundle script.
Shim AngularJS so that it is attached to an exports object rather than the window (using something like browserify-shim), then importing it using require like any other module.
I tend to prefer the second approach because it's kind of weird to use Browserify to give you module scope and then make the major dependency of your project a window global.
However, AngularJS already has its own dependency-injection driven module system. When you declare angularJS components, you're attaching them to module objects which themselves have been attached to the angular object. This means that the exports object for your angularJS module files is essentially redundant in the case of Angular, since as long as the file executes then the angular object will be augmented with your module and components.
You still need to 'require' the files since otherwise Browserify won't bundle them, they'll never execute, and they'll never augment the angular object with your modules. But you don't need to add anything to the exports for Angular, since the angular object is your exports.
So why did I spend all this time explaining how CommonJS modules and exports work? Because hopefully the other reason why you are using Browserify is to allow you to make use of modules hosted on NPM in your browser application. Most of those modules are non-angular commonJS modules, meaning their functionality is exposed via an exports. In this case it's important to capture their exports in a variable when you require them, such as I'm doing in c.js above. Similarly, if you write some modules and release them to NPM, your users are going to expect you'll be adding the entry point to your module to the exports object of the file declared as main in your package.json.

Resources