I'm using webpack, angular 1.x and have the following code
import angular from 'angular';
which works good, but the problem is that included file is too big (angularjs - 1.15mb). It will be better of course to use minified version of angularjs, but when I change code to
import angular from 'angular/angular.min.js';
it doesn't work properly, I mean it seems like angular.min.js doesn't export appropriate angular object.
What's the right way to use minified version of library?
I've found github issue regarding the problem, it's good idea to use exports-loader. My solution is:
webpack.config.js
...
// Add alias, so webpack looks for minified version of angular
resolve: {
alias: {
angular: "angular/angular.min.js"
}
}
...
// Add exports loader for angular
modules: {
loaders: [
{
test: /angular\.min\.js$/,
loader: 'exports?angular'
}
]
}
After this configuration we can easily import minified version of angular using the following command
let angular = require('angular');
// or es6 version
import angular from 'angular';
U can use angular cli and just type
ng build -prod
Then your minified file are in dist foldeer. It must be smaller, and u can upload that ini your public_html
Related
I'm converting an existing AngularJS application to a hybrid application, to begin incrementally upgrading it to Angular 4. I want to understand how Angular 4 needs to be referenced in the existing AngularJS. In the existing AngularJS application, it's clear how the AngularJS framework is being loaded - it's simply an included script file:
<script src="/angular/angular.js"></script>
To familiarise myself with an up to date Angular version, I've created a separate 'quickstart' Angular 5 application using the Angular quickstart guide at https://angular.io/guide/quickstart, and I can run it using:
ng serve --open
When I look at the project files though, I'm not seeing where the angular framework is actually being loaded. There is no script being included anywhere in the src/index.html file for that application, it simply declares an directive for a component (app.component.ts) that looks like this:
import { Component } from '#angular/core';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'Test Angular 5 app';
}
Where does the import actually import from? The Angular documentation says about the index.html file that it is:
The main HTML page that is served when someone visits your site. Most
of the time you'll never need to edit it. The CLI automatically adds
all js and css files when building your app so you never need to add
any or tags here manually.
So what is happening here? How is #angular/core actually being referenced?
When using Angular CLI, we have a lot of moving parts. To really understand what's happening, we should review some of the core technologies used in Angular CLI as they relate to output files and module resolution:
TypeScript -- will transpile your TypeScript code to ES5 or ES6 (most commonly ES5). The transpiled code will use CommonJS modules by default if the target is ES5. If the target is ES6, then ES6 modules will be used.
Webpack -- will take your transpiled TypeScript code and build a dependency graph of your import / exports based on the entry points defined in webpack.config.js. This dependency graph will include all of your modules and it will package these modules into 1+ bundles, depending on the configuration. This is the step where the #angular/core dependency (which lives in node_modules/#angular/core) is processed by Webpack and added to a bundle that can be accessed at runtime.
You can load the generated bundles into the page by including the generated files in your HTML. In the case of JS files, you load them using the script tag like you did with AngularJS.
Because we are using Angular CLI, there are a lot of configurations within Webpack that are set up by default, so we will have multiple generated bundles.
I just created an empty Angular CLI project and inspected the HTML to see the 5 generated bundles:
At the core of the complexity when comparing Angular project files with AngularJS files is that Angular code is transformed through multiple build steps, while AngularJS code is normally used out-of-the-box with ES5. If you were to add Webpack and TypeScript to your AngularJS build, you would see something very similar to the Angular output.
Where is Webpack Configured in Angular CLI?
Under the hood, Angular CLI uses Webpack to build your project and bundle your files.
The Angular team chose not to expose a configurable Webpack configuration file for Angular CLI, but they did add ng eject, which generates a webpack.config.js that matches the Webpack build of your project. The downside of ejecting is that you will no longer use ng serve to serve your project. Instead, you'll use npm run build && npm run start (you'll see these scripts added to your package.json after you eject), which will build and serve your project based on the generated webpack.config.js file.
This feature is essential if you need to make custom modifications to the default Webpack build.
Read more about ng eject here.
Where are the generated bundles?
If you are using ng serve, you won't see any of your generated files because these are being served from memory and not from disk (to speed up development when files are constantly changing), so your generated files are not located in any folder.
If you want to see your generated files, you can run ng build, which will create a dist folder with the index.html and associated assets/bundles.
Note that by default, all commands that build or serve your project will delete your dist folder unless you pass the --no-delete-output-path when building/serving.
You need to understand how imports and exports work in TypeScript
From TypeScript Docs
Exporting a declaration
Any declaration (such as a variable, function, class, type alias, or
interface) can be exported by adding the export keyword.
Validation.ts
export interface StringValidator {
isAcceptable(s: string): boolean;
}
ZipCodeValidator.ts
export const numberRegexp = /^[0-9]+$/;
export class ZipCodeValidator implements StringValidator {
isAcceptable(s: string) {
return s.length === 5 && numberRegexp.test(s);
}
}
Export statements
Export statements are handy when exports need to be renamed for
consumers, so the above example can be written as:
ZipCodeValidator.ts
class ZipCodeValidator implements StringValidator {
isAcceptable(s: string) {
return s.length === 5 && numberRegexp.test(s);
}
}
export { ZipCodeValidator };
export { ZipCodeValidator as mainValidator };
Import
Importing is just about as easy as exporting from a module. Importing
an exported declaration is done through using one of the import forms
below:
Import a single export from a module
import { ZipCodeValidator } from "./ZipCodeValidator";
let myValidator = new ZipCodeValidator();
imports can also be renamed
import { ZipCodeValidator as ZCV } from "./ZipCodeValidator";
let myValidator = new ZCV();
Import the entire module into a single variable, and use it to access the module exports
import * as validator from "./ZipCodeValidator";
let myValidator = new validator.ZipCodeValidator();
Since you followed the Angular quickstart guide you must have used npm which is used to install your modules and dependencies.
If you read angular.io/npm
#angular/core: Critical runtime parts of the framework needed by every
application. Includes all metadata decorators, Component, Directive,
dependency injection, and the component lifecycle hooks.
And by default npm stores all your dependencies in node_modules directory.
So you are importing Component from #angular/core which lives inside node_modules directory.
I would like to use the dat.GUI library for a project that's build with Webpack 2. If I install the module via npm -install --save-dev dat.gui and then try to import it using import * as DAT from 'dat.gui'; I get the following error when Webpack is trying to compile my project:
ERROR in ./~/dat.gui/src/dat/controllers/NumberControllerSlider.js
Module not found: Error: Can't resolve 'style' in
'/home/me/myProject/node_modules/dat.gui/src/dat/controllers'
BREAKING CHANGE: It's no longer allowed to omit the '-loader' suffix
when using loaders.
I know this error occurs when using Webpack 2 to build Webpack 1 based projects. But why is Webpack even trying to build the module if there already is a build version inside node_modules/dat.gui/build';? Is there a way to tell Webpack or NPM to use the existing build version without trying to re-build it?
When importing a node module, webpack looks into its package.json and uses the main field as entry of the module, similar to what Node.js does (webpack looks for more fields by default, see resolve.mainFields).
Since for dat.gui the main field does not point to the built version but to the source, which actually inlines loaders as seen in dat.gui#0.6.1 - NumberControllerSlider.js for the styleSheet import, and that is not a good idea in general and certainly not to publish.
But you can import the built version by specifying the corresponding path. So your import would be:
import * as DAT from 'dat.gui/build/dat.gui.js';
If you'd like to still import just dat.gui you can configure resolve.alias to point to the built version as follows:
resolve: {
alias: {
'dat.gui': 'dat.gui/build/dat.gui.js'
}
}
With that you can use your original import statement:
import * as DAT from 'dat.gui';
I have a Webpack angular 2 application and I have a date picker module dependency with a library using Moment. The thing is that if I don't import it like :
<script src="./../node_modules/moment/min/moment.min.js"></script>
a moment is not defined error is raised if I want to use it. I tried to import moment with require but it's not taken into account.
The problem is that the script src tag works in local but in the webpack builded version we need to deploy the path with node_modules doesn't exist anymore. Is there a way to do it other than hard paste moment.min.js in a lib folder?
Add the following code in webpack.conf.js:
resolve: {
alias: {
'moment': 'moment/min/moment.min'
}
}
Now you can simply do, require('moment') in your js file.
Note: By default webpack searches the file in node_modules folder. You can instruct it to look into specific places using modules property of resolve object.
The resulting code would look like:
resolve: {
modules: ['lib/','some_folder/node_modules'...],
alias: {
'moment': 'moment/min/moment.min'
}
}
Our project is using the webpack resolve.root option to import modules with absolute paths. (avoiding something like ../../../module)
In its current state the project is using babel-loader which works perfectly fine.
My task is to migrate the app to Angular 2.
Therefor I am currently in the process of transitioning to TypeScript.
Somehow it seems like the ts-loader does not work in combination with the resolve.root option of the webpack config.
Example of the webpack.config.js
resolve: {
root: [
path.resolve('./node_modules'),
path.resolve('./app'),
path.resolve('./app/lib'),
]
},
Example of a module import
import AbstractListState from 'states/abstract_list_state';
The states directory is inside the app/lib directory.
Error when executing webpack
ERROR in ./app/mainViews/panel/panel.controller.ts
Module not found: Error: Cannot resolve module 'states/abstract_list_state' in C:\Users\...\Project\app\mainViews\panel
# ./app/mainViews/panel/panel.controller.ts 4:28-65
Pre version 2.0 TypeScript will try to load modules with an absolute path from the node_modules directory. This is because TypeScript's module resultion is per default set to "node". Which means it works like node's require method. So, even if you're using webpack to build your app, TypeScript (and its compiler) will still want to load the files.
In order to let webpack import your modules with absolute path you have to go back and use the require method. This way TypeScript will let webpack import stuff. But of course you will not get any type-inference, autocomplete, ...
Or, you update to the TypeScript 2.0 beta and give this a try: https://github.com/Microsoft/TypeScript/wiki/What%27s-new-in-TypeScript#module-resolution-enhancements-baseurl-path-mapping-rootdirs-and-tracing
I am writing 3 modules to be published as npm modules
Admin (has core has a dependency)
Member (has core has a dependency)
Core
package.json in Core:
{
...
"main":"dist/bundle.js"
}
usage of core in Admin:
import core from "core"
All modules are built by webpack.
The problem is that if I use webpack to build Core, generating bundle.js, and have Admin to import bundle.js lots of libraries will be duplicated.
E.g. Angular, bootstrap etc..
What I am doing now is to import the entry file src/index.js in admin
package.json in Core:
{
...
"main":"src/index.js"
}
usage of core in Admin:
import core from "core"
but webpack cannot resolve some dependencies in core correctly, for example, I have set up more than one root in webpack.config.js in core module, so that some short hand import is possible.
root: [
path.resolve(__dirname, './src/'),
path.resolve(__dirname, './src/directives')
]
// instead of relative path
import "../../myDirective.js"
// I can use
import "myDirective.js"; // where myDirective.js is under "src/directives/myDirective.js", but this fails when I try to build `admin` module.
Is there a simpler way for webpack to build npm-modules so that it is easy to import?
Core: depends on angular, bootstrap, core.js
Admin: depends on angular, bootstrap, admin.js, includes core as a module
It's interesting to me too. I suggest it can be done by setting webpack's library options.