I'm inspecting this Webpack demo project https://github.com/Foxandxss/GermanWords-ng1-webpack. This project contains in several files this line (features/home/index, features/login/index):
import angular from 'angular';
I don't understand - if 'angular' library will be included several times in result js file because this library exists in several source files? I've looked at webpack config file, but can't understand. Please, can you clear this questions?
It's just to be sure that angular will be available for every module. Imagine you use a feature to be a new standalone site, you will have already the code ready. Always think like every feature is a standalone (handle routes, dependencies, controllers, views etc.).
Webpack will handle the dependencies and inject only once angular, dont worry. Like #thsorens says in comments : "All dependencies in your files needs to be imported where it is used."
Oh and for furthermore, i've found this yeoman generator base on Foxandxss work : https://github.com/Aleksion/generator-angular-webpack-babel
Have fun.
Related
I have a two-year-old AngularJs 1.x project, which is built with Gulp for development and Grunt for production (don't ask me why; I don't know either).
The build process is basically:
Compile all scss files into one css file
Merge all JS files into one JS file. We are not using any import mechanism. Each file is basically one of AngularJs' controller, component, service or filter. Something like this:
angular.module("myApp").controller("myCtrl", function() {//...});
Merge all html templates into one JS file. Each template is hardcoded with $templateCache.
Moving assets like images and fonts into the build folder.
Moving third-party libraries into the build folder.
Now I want to switch to webpack for this project. I want to incrementally modernize this project, but the first step would be just building it with webpack with a similar process like the above. I would like to keep the code base as much the same as possible. I don't want to add import for all the JS files yet. There are too many. I would also like to add a babel-loader.
I have some basic concepts about webpack, but never really customized the configuration myself.
Would anyone please give me some pointers? Like which loaders/plugins would I need, etc.? Thanks!
My process to do such a transition was gradual, I had a similar Grunt configuration.
These are my notes & steps in-order to transition to Webpack stack.
The longest step was to refactor the code so it will use ES6 imports/exports (yeah, I know you have said that it is not a phase that you wanna make, but it is important to avoid hacks).
At the end each file looks like that:
//my-component.js
class MyComponentController { ... }
export const MyComponent = {
bindings: {...},
controller: MyComponentController,
template: `...`
}
//main.js
import {MyComponent} from 'my-component'
angular.module('my-module').component('myComponent', MyComponent);
In order not going over all the files and change them, we renamed all js files and added a suffix of .not_module.js.
Those files were the old untouched files.
We added grunt-webpack as a step to the old build system (based on Grunt).
It processed via Webpack all the new files (those that are without .not_module.js suffix).
That step produced only one bundle that contains all the files there were converted already, that file we have added to concat step.
One by one, each converted file gradually moved from being processed by Grunt tasks to be processed by Webpack.
You can take as a reference that webpack.config.
Good luck.
When I work with angular2 code I often need to see the implementation of a class, let's say the Router class.
If I click on the Router type in my IDE WebStorm, e. g. inside the constructor of another class
export class myClass {
constructor(private router: Router) {}
// ...
}
my IDE takes me to the TypeScript definition file router.d.ts inside my node_modules folder. What I want is it to take me to the original router.ts file with the implementation of the router class, not just its definition.
The original .ts file is not included in the node_modules folder structure when you get angular2 from github via the standard package.json suggested in the Angular2 Quickstart. Currently, I have to look up the original code in the official github repo.
Any ideas how to get the .ts files into my node_modules/#angular folder instead of the .d.ts files?
Sadly, it's not possible since no TS files exist. Even if you add them it still not possible since you import real angular paths which always point to the definition files. On top of that the file structure of the project does not correlate to the structure of the import string literals.
Some background and more information
The NPM package does not include .ts files, this is by design from the angular team. Up until some time ago the .ts files were indeed supplied with the NPM package.
The reasoning for removing them is to disable abuse from users accessing private classes and #internal and private APIs which is public methods/properties in the API that are not supposed to be public but must be so other angular internal classes can use them.
We used to see a lot of code samples out there doing things like import { PromiseCompleter } from 'angular2/src/facade/lang'; (before RC0) but this was changed when the project structure had a big structure refactor in RC0. This abuse was wide and it's bad, very bad... For users and for Angular PR.
The Angular project has a complex and robust build process where all of the API is moved from .ts files into d.ts files using an automated process that limits exposure. (public_api_guard)
The end result is d.ts files only.
It's also not possible to clone the git repo and use it since, again, the file structure is way way different so imports will have to change. Most importantly without the build Angular will, most likely, not work.
A solution using a different approach
However, if you debug your app you notice that you reach actual angular core .ts files in the source view of the console, this is because the NPM package comes with source map files that include the whole TS source code. Nice trick they did there.
This is what I use to dig deep into angular, it works quite great and I get a lot from it.
It's not as nice as Goto Declaration but it something...
IMO it's also easier to understand when you step through code...
I have a javascript project consisting of two js-files
component.js
component.angular.js
component.js contains the actual logic exported to globals, amd or whatever. It can be used as-is if you are not using angular.
component.angular.js wraps the the logic in an angular directive, but requires the logic from component.js.
I would like to register/publish both a non-angular (only need component.js) and a angular (need both component.js and component.angular.js) version of this component in Bower.
Overall question: How to do that?
Questions that might help you figure out why I am confused:
Can you even state that two js-files needs to be used in a bower.json?
I guess registering the repository where the code lives in Bower, it will look for a bower.json file. But I guess I cannot state in a bower.json that you will need both files in case of angular and only one of them in case of non-angular.
Can I have two different bower.json files in the same repository? And register them under two different names in Bower - e.g. under "mycomponent" and "mycomponent-angular".
Do I need two repositories?
Well, I ended up having two repostories. One for sharing the raw component (on bower, npm and meteor) and one for sharing the angular wrapping depending on the raw component (also on bower, npm and meteor).
Raw component: https://github.com/TeletronicsDotAe/infinite-gallery
Angular wrapper: https://github.com/TeletronicsDotAe/infinite-gallery-angular
Do not know if that is the best way, but it works for me.
There are many ways to format JavaScript modules: AMD, CommonJS, UMD, ES6, global script. I've seen projects that structure their source code in whatever way they want and run a build process to generate a dist directory containing code in all the above formats. This has the advantage that the user of the code can just pick whichever format is most applicable to his environment.
This method works fine as long as the module has no dependencies on other modules. In the case where the modules must import other modules, there are implied complications. For example RequireJS uses a config file that looks like:
requirejs.config({
paths: {
'jquery': 'js/lib/jquery',
'ember': 'js/lib/ember',
'handlebars': 'js/lib/handlebars',
'underscore': 'js/lib/underscore'
}
});
Other loaders have equivalent mechanisms for mapping import paths.
If jQuery is a dependency, should the module import it from the path 'jquery'? What if the system in which it is being incorporated stores jQuery at the path 'libs/jquery'? In this case, is it the responsibility of the author of the system incorporating jQuery to provide aliases in the configuration of the import path?
This questioning strongly suggests that a truly reusable module must provide code formatted in all module formats as well as document clearly upon what libraries (and versions thereof) it depends and document what import paths at which those libraries are assumed to exist.
For example I could author a fancy jQuery plugin that I distribute in AMD, CommonJS, ES6, and global variations. I would document that this plugin depends on jQuery version 2.0 imported through the path 'jquery_on_a_path_that_confuses_you'. The would-be user of this plugin must copy the plugin into his project and then configure his module loader or build tool to export jQuery at the path 'jquery_on_a_path_that_confuses_you'.
As far as I can tell:
There is no standard for what to use for import paths.
There is no standard way to express the dependency, version, and import path requirements to the user of a piece of code.
There is no standard remedy to deal with clashing import paths or load multiple versions of a library.
Does there exist any plan to deal with this strange arrangement? To me it seems a little crazy to have module systems that don't know how to name their modules. Am I wrong?
You may want to check jspm.io + SystemJS which is a relatively new package manager and universal module loader which is increasing in popularity.
Please find below some presentations and article on the subject I found useful:
https://www.youtube.com/watch?v=MXzQP38mdnE,
https://vimeo.com/65042246,
https://www.youtube.com/watch?v=szJjsduHBQQ,
http://javascriptplayground.com/blog/2014/11/js-modules-jspm-systemjs/
Late with the answer, but if you're after writing plain JS code (without jQuery or other frameworks), I've found that there's the deploader.js repo, which you can use to wrap any kind of JS into modules and do dependency loading.
May worth checking out.
I'm currently working on a big JavaScript project for which we want to define our own API. I'm using RequireJS as my dependency loader and it suits me just fine, allowing me to define modules in their respective file. I do not make use of my own namespace, a module returns an instance, which can be used in other modules, i.e.:
define(
['imported_module'],
function(module){
module.doSomething();
}
)
However as the number of files grows, I'd like to decide how to structure these files in folders. Currently I use the following scheme to name my files:
[projectname].[packagename].[ModuleName]
An example could be stackoverflow.util.HashMap.js. I would like to introduce a project folder, a folder per package and rename the files to the module name, like:
stackoverflow/util/HashMap.js
This structures my code quite neatly into folders, however the filename reflects only the module now. I'd like to define some kind of routing to be able to define how RequireJS should look for files. Example:
The file
stackoverflow/util/stackoverflow.util.HashMap.js
Should be importable by the statement
define(['stackoverflow.util.HashMap'],function(HashMap){});
Has anyone experience with structuring large JavaScript projects and if so, could you share your approach?
You shouldn't specify the routing info on your js file names, those are the namespace and folder paths' jobs. So stackoverflow/util/HashMap.js is just fine. And you can use define("stackoverflow/util/HashMap", ....) to tell the dependency.
If you need to put your modules in a different folders, you can config paths for your loader, see this manual from RequireJS API.
There's no best way for structure your js files. But put the root namespace in a src folder is always a good practice. You can see the dojo source code and YUI source code and use similar ways for your project. They both are large scale Javascript projects.
actually it's better to get js lib routing to load all js using standard interface: "js.yoursite.com/lib-0.2.js" there should be a router (php or other, and able to cache queries). So there you could determine and control whole pathes that you use. Because common jquery plugin should stay at one dir, with jquery, and your own custom plugins not.
And there you control each project by it's own rules:
jquery/
plugins/
jquery.prettyPhoto.js
jquery.min.js
mySuperJS/
stable.0/ -- there your production version for 1.0 branch
module.js
0.1/
module.js
0.2/
module.js
0.3/
module.js
myOtherlib/
stable.0/ -- production version for all 0.* versions
stable.1/ -- production version for all 1.0 versions
0.1/
0.2/
0.3/
0.4/
0.4.1/
0.4.1.18/
We're using such structure around a year and it's the best for us. But sometimes we use more complex solution and separate all modules for libs, plugins, tools, components and apps.