Skip to content

Commit 6f4cfc0

Browse files
committed
chore(docs): add global lib docs
1 parent 2b7f8c4 commit 6f4cfc0

File tree

5 files changed

+127
-33
lines changed

5 files changed

+127
-33
lines changed

README.md

+39
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ The generated project has dependencies that require **Node 4 or greater**.
4747
* [Global styles](#global-styles)
4848
* [CSS preprocessor integration](#css-preprocessor-integration)
4949
* [3rd Party Library Installation](#3rd-party-library-installation)
50+
* [Global Library Installation](#global-library-installation)
5051
* [Updating angular-cli](#updating-angular-cli)
5152
* [Known Issues](#known-issues)
5253
* [Development Hints for hacking on angular-cli](#development-hints-for-hacking-on-angular-cli)
@@ -250,6 +251,8 @@ The `styles.css` file allows users to add global styles and supports
250251
If the project is created with the `--style=sass` option, this will be a `.sass`
251252
file instead, and the same applies to `scss/less/styl`.
252253

254+
You can add more global styles via the `apps[0].styles` property in `angular-cli.json`.
255+
253256
### CSS Preprocessor integration
254257

255258
Angular-CLI supports all major CSS preprocessors:
@@ -296,6 +299,42 @@ npm install moment --save
296299
npm install @types/moment --save-dev
297300
```
298301

302+
### Global Library Installation
303+
304+
Some javascript libraries need to be added to the global scope, and loaded as if
305+
they were in a script tag. We can do this using the `apps[0].scripts` and
306+
`apps[0].styles` properties of `angular-cli.json`.
307+
308+
As an example, to use [Boostrap 4](http://v4-alpha.getbootstrap.com/) this is
309+
what you need to do:
310+
311+
First install Bootstrap from `npm`:
312+
313+
```bash
314+
npm install bootstrap@next
315+
```
316+
317+
Then add the needed script files to to `apps[0].scripts`.
318+
319+
```
320+
"scripts": [
321+
"../node_modules/jquery/dist/jquery.js",
322+
"../node_modules/tether/dist/js/tether.js",
323+
"../node_modules/bootstrap/dist/js/bootstrap.js"
324+
],
325+
```
326+
327+
Finally add the Bootstrap CSS to the `apps[0].styles` array:
328+
```
329+
"styles": [
330+
"styles.css",
331+
"../node_modules/bootstrap/dist/css/bootstrap.css"
332+
],
333+
```
334+
335+
Restart `ng serve` if you're running it, and Bootstrap 4 should be working on
336+
your app.
337+
299338
### Updating angular-cli
300339

301340
To update `angular-cli` to a new version, you must update both the global package and your project's local package.

addon/ng2/blueprints/ng2/files/angular-cli.json

+4-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@
1414
"tsconfig": "tsconfig.json",
1515
"prefix": "<%= prefix %>",
1616
"mobile": <%= isMobile %>,
17-
"styles": "styles.<%= styleExt %>",
17+
"styles": [
18+
"styles.<%= styleExt %>"
19+
],
20+
"scripts": [],
1821
"environments": {
1922
"source": "environments/environment.ts",
2023
"prod": "environments/environment.prod.ts",

addon/ng2/models/webpack-build-common.ts

+18-4
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,26 @@ export function getWebpackCommonConfig(projectRoot: string, environment: string,
1010

1111
const appRoot = path.resolve(projectRoot, appConfig.root);
1212
const appMain = path.resolve(appRoot, appConfig.main);
13-
const styles = path.resolve(appRoot, appConfig.styles);
13+
const styles = appConfig.styles.map(style => path.resolve(appRoot, style));
14+
const scripts = appConfig.scripts.map(script => path.resolve(appRoot, script));
1415
const lazyModules = findLazyModules(appRoot);
1516

17+
let entry = {
18+
main: [appMain]
19+
};
20+
21+
// Only add styles/scripts if there's actually entries there
22+
if (appConfig.styles.length > 0) entry.styles = styles;
23+
if (appConfig.scripts.length > 0) entry.scripts = scripts;
24+
1625
return {
1726
devtool: 'source-map',
1827
resolve: {
1928
extensions: ['', '.ts', '.js'],
2029
root: appRoot
2130
},
2231
context: path.resolve(__dirname, './'),
23-
entry: {
24-
main: [appMain, styles]
25-
},
32+
entry: entry,
2633
output: {
2734
path: path.resolve(projectRoot, appConfig.outDir),
2835
filename: '[name].bundle.js'
@@ -66,6 +73,9 @@ export function getWebpackCommonConfig(projectRoot: string, environment: string,
6673
       { include: styles, test: /\.less$/, loaders: ['style-loader', 'css-loader', 'postcss-loader', 'less-loader'] },
6774
       { include: styles, test: /\.scss$|\.sass$/, loaders: ['style-loader', 'css-loader', 'postcss-loader', 'sass-loader'] },
6875

76+
// load global scripts using script-loader
77+
{ include: scripts, test: /\.js$/, loader: 'script-loader' },
78+
6979
       { test: /\.json$/, loader: 'json-loader' },
7080
       { test: /\.(jpg|png)$/, loader: 'url-loader?limit=10000' },
7181
       { test: /\.html$/, loader: 'raw-loader' },
@@ -90,6 +100,10 @@ export function getWebpackCommonConfig(projectRoot: string, environment: string,
90100
.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&")),
91101
path.resolve(appRoot, appConfig.environments[environment])
92102
),
103+
new webpack.optimize.CommonsChunkPlugin({
104+
// Optimizing ensures loading order in index.html
105+
name: ['styles', 'scripts', 'main'].reverse();
106+
}),
93107
new webpack.optimize.CommonsChunkPlugin({
94108
minChunks: Infinity,
95109
name: 'inline',

lib/config/schema.json

+11-19
Original file line numberDiff line numberDiff line change
@@ -49,27 +49,19 @@
4949
"mobile": {
5050
"type": "boolean"
5151
},
52-
"additionalEntries": {
53-
"description": "Additional files to be included in the build.",
52+
"styles": {
53+
"description": "Global styles to be included in the build.",
5454
"type": "array",
5555
"items": {
56-
"anyOf": [
57-
{
58-
"type": "string"
59-
},
60-
{
61-
"type": "object",
62-
"properties": {
63-
"input": {
64-
"type": "string"
65-
},
66-
"output": {
67-
"type": "string"
68-
}
69-
},
70-
"additionalProperties": false
71-
}
72-
]
56+
"type": "string"
57+
},
58+
"additionalProperties": false
59+
},
60+
"scripts": {
61+
"description": "Global scripts to be included in the build.",
62+
"type": "array",
63+
"items": {
64+
"type": "string"
7365
},
7466
"additionalProperties": false
7567
},

tests/e2e/e2e_workflow.spec.js

+55-9
Original file line numberDiff line numberDiff line change
@@ -486,7 +486,7 @@ describe('Basic end-to-end Workflow', function () {
486486
expect(indexHtml).to.include('main.bundle.js');
487487
});
488488

489-
it('styles.css is added to main bundle', function() {
489+
it('styles.css is added to styles bundle', function() {
490490
this.timeout(420000);
491491

492492
let stylesPath = path.join(process.cwd(), 'src', 'styles.css');
@@ -495,10 +495,10 @@ describe('Basic end-to-end Workflow', function () {
495495

496496
sh.exec(`${ngBin} build`);
497497

498-
var mainBundlePath = path.join(process.cwd(), 'dist', 'main.bundle.js');
499-
var mainBundleContent = fs.readFileSync(mainBundlePath, { encoding: 'utf8' });
498+
var stylesBundlePath = path.join(process.cwd(), 'dist', 'styles.bundle.js');
499+
var stylesBundleContent = fs.readFileSync(stylesBundlePath, { encoding: 'utf8' });
500500

501-
expect(mainBundleContent.includes(testStyle)).to.be.equal(true);
501+
expect(stylesBundleContent.includes(testStyle)).to.be.equal(true);
502502
});
503503

504504
it('styles.css supports css imports', function() {
@@ -508,16 +508,62 @@ describe('Basic end-to-end Workflow', function () {
508508
let testStyle = 'body { background-color: blue; }';
509509
fs.writeFileSync(importedStylePath, testStyle, 'utf8');
510510

511-
let stylesPath = path.join(process.cwd(), 'src', 'style.css');
512-
let importStyle = '@import \'./imported-style.css\';';
511+
let stylesPath = path.join(process.cwd(), 'src', 'styles.css');
512+
let importStyle = '@import \'./imported-styles.css\';';
513513
fs.writeFileSync(stylesPath, importStyle, 'utf8');
514514

515515
sh.exec(`${ngBin} build`);
516516

517-
var mainBundlePath = path.join(process.cwd(), 'dist', 'main.bundle.js');
518-
var mainBundleContent = fs.readFileSync(mainBundlePath, { encoding: 'utf8' });
517+
var stylesBundlePath = path.join(process.cwd(), 'dist', 'styles.bundle.js');
518+
var stylesBundleContent = fs.readFileSync(stylesBundlePath, { encoding: 'utf8' });
519+
520+
expect(stylesBundleContent).to.include(testStyle);
521+
});
522+
523+
it('build supports global styles and scripts', function() {
524+
this.timeout(420000);
525+
526+
sh.exec('npm install bootstrap@next', { silent: true });
527+
528+
const configFile = path.join(process.cwd(), 'angular-cli.json');
529+
let originalConfigContent = fs.readFileSync(configFile, { encoding: 'utf8' });
530+
let configContent = originalConfigContent.replace('"styles.css"', `
531+
"styles.css",
532+
"../node_modules/bootstrap/dist/css/bootstrap.css"
533+
`).replace('"scripts": [],',`
534+
"scripts": [
535+
"../node_modules/jquery/dist/jquery.js",
536+
"../node_modules/tether/dist/js/tether.js",
537+
"../node_modules/bootstrap/dist/js/bootstrap.js"
538+
],
539+
`);
540+
541+
fs.writeFileSync(configFile, configContent, 'utf8');
542+
543+
sh.exec(`${ngBin} build`);
519544

520-
expect(mainBundleContent.includes(testStyle)).to.be.equal(true);
545+
// checking for strings that are part of the included files
546+
const stylesBundlePath = path.join(process.cwd(), 'dist', 'styles.bundle.js');
547+
const stylesBundleContent = fs.readFileSync(stylesBundlePath, { encoding: 'utf8' });
548+
expect(stylesBundleContent).to.include('* Bootstrap ');
549+
550+
const scriptsBundlePath = path.join(process.cwd(), 'dist', 'scripts.bundle.js');
551+
const scriptsBundleContent = fs.readFileSync(scriptsBundlePath, { encoding: 'utf8' });
552+
expect(scriptsBundleContent).to.include('* jQuery JavaScript');
553+
expect(scriptsBundleContent).to.include('/*! tether ');
554+
expect(scriptsBundleContent).to.include('* Bootstrap ');
555+
556+
// check the scripts are loaded in the correct order
557+
const indexPath = path.join(process.cwd(), 'dist', 'index.html');
558+
const indexContent = fs.readFileSync(indexPath, { encoding: 'utf8' });
559+
let scriptTags = '<script type="text/javascript" src="inline.js"></script>' +
560+
'<script type="text/javascript" src="styles.bundle.js"></script>' +
561+
'<script type="text/javascript" src="scripts.bundle.js"></script>' +
562+
'<script type="text/javascript" src="main.bundle.js"></script>'
563+
expect(indexContent).to.include(scriptTags);
564+
565+
// restore config
566+
fs.writeFileSync(configFile, originalConfigContent, 'utf8');
521567
});
522568

523569
it('Serve and run e2e tests on dev environment', function () {

0 commit comments

Comments
 (0)