Skip to content

Commit 3e8ee8a

Browse files
committed
feat(@angular/cli): add an eject command
The command will generate a webpack.config.js and will add scripts to the package.json.
1 parent 9db71d8 commit 3e8ee8a

File tree

30 files changed

+712
-41
lines changed

30 files changed

+712
-41
lines changed

.travis.yml

+3
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ matrix:
2525
- node_js: "6"
2626
os: linux
2727
env: NODE_SCRIPT="tests/run_e2e.js --glob=tests/build/**"
28+
- node_js: "6"
29+
os: linux
30+
env: NODE_SCRIPT="tests/run_e2e.js --eject --glob=tests/build/**"
2831
- node_js: "6"
2932
os: linux
3033
env: NODE_SCRIPT="tests/run_e2e.js --ignore=**/tests/build/**"

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@
117117
"@types/express": "^4.0.32",
118118
"@types/fs-extra": "0.0.37",
119119
"@types/glob": "^5.0.29",
120-
"@types/jasmine": "^2.2.32",
120+
"@types/jasmine": "~2.2.0",
121121
"@types/lodash": "4.14.50",
122122
"@types/mock-fs": "^3.6.30",
123123
"@types/node": "^6.0.36",

packages/@angular/cli/addon/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ module.exports = {
2121
return {
2222
'build': require('../commands/build').default,
2323
'serve': require('../commands/serve').default,
24+
'eject': require('../commands/eject').default,
2425
'new': require('../commands/new').default,
2526
'generate': require('../commands/generate').default,
2627
'destroy': require('../commands/destroy').default,

packages/@angular/cli/blueprints/ng2/files/__path__/tsconfig.json

+5-1
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,9 @@
1717
"typeRoots": [
1818
"<%= relativeRootPath %>/node_modules/@types"
1919
]
20-
}
20+
},
21+
"exclude": [
22+
"test.ts",
23+
"**/*.spec.ts"
24+
]
2125
}
+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import { BuildOptions } from '../models/build-options';
2+
import { Version } from '../upgrade/version';
3+
4+
const Command = require('../ember-cli/lib/models/command');
5+
6+
// defaults for BuildOptions
7+
export const baseEjectCommandOptions: any = [
8+
{
9+
name: 'target',
10+
type: String,
11+
default: 'development',
12+
aliases: ['t', { 'dev': 'development' }, { 'prod': 'production' }]
13+
},
14+
{ name: 'environment', type: String, aliases: ['e'] },
15+
{ name: 'output-path', type: 'Path', aliases: ['op'] },
16+
{ name: 'aot', type: Boolean },
17+
{ name: 'sourcemap', type: Boolean, aliases: ['sm', 'sourcemaps'] },
18+
{ name: 'vendor-chunk', type: Boolean, default: true, aliases: ['vc'] },
19+
{ name: 'base-href', type: String, aliases: ['bh'] },
20+
{ name: 'deploy-url', type: String, aliases: ['d'] },
21+
{ name: 'verbose', type: Boolean, default: false, aliases: ['v'] },
22+
{ name: 'progress', type: Boolean, default: true, aliases: ['pr'] },
23+
{ name: 'i18n-file', type: String },
24+
{ name: 'i18n-format', type: String },
25+
{ name: 'locale', type: String },
26+
{ name: 'extract-css', type: Boolean, aliases: ['ec'] },
27+
{
28+
name: 'output-hashing',
29+
type: String,
30+
values: ['none', 'all', 'media', 'bundles'],
31+
description: 'define the output filename cache-busting hashing mode',
32+
aliases: ['oh']
33+
},
34+
{ name: 'force', 'type': Boolean }
35+
];
36+
37+
export interface EjectTaskOptions extends BuildOptions {
38+
force?: boolean;
39+
}
40+
41+
42+
const EjectCommand = Command.extend({
43+
name: 'eject',
44+
description: 'Ejects your app and output the proper webpack configuration and scripts.',
45+
46+
availableOptions: baseEjectCommandOptions,
47+
48+
run: function (commandOptions: EjectTaskOptions) {
49+
const project = this.project;
50+
const EjectTask = require('../tasks/eject').default;
51+
const ejectTask = new EjectTask({
52+
cliProject: project,
53+
ui: this.ui,
54+
});
55+
56+
return ejectTask.run(commandOptions);
57+
}
58+
});
59+
60+
61+
export default EjectCommand;

packages/@angular/cli/lib/base-href-webpack/base-href-webpack-plugin.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ export interface BaseHrefWebpackPluginOptions {
33
}
44

55
export class BaseHrefWebpackPlugin {
6-
constructor(private options: BaseHrefWebpackPluginOptions) { }
6+
constructor(public readonly options: BaseHrefWebpackPluginOptions) { }
77

88
apply(compiler: any): void {
99
// Ignore if baseHref is not passed

packages/@angular/cli/lib/config/schema.json

+4
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@
1313
},
1414
"name": {
1515
"type": "string"
16+
},
17+
"ejected": {
18+
"type": "boolean",
19+
"default": false
1620
}
1721
},
1822
"additionalProperties": false

packages/@angular/cli/models/webpack-configs/common.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { WebpackConfigOptions } from '../webpack-config';
99
const autoprefixer = require('autoprefixer');
1010
const ProgressPlugin = require('webpack/lib/ProgressPlugin');
1111
const HtmlWebpackPlugin = require('html-webpack-plugin');
12-
const ExtractTextPlugin = require('extract-text-webpack-plugin');
12+
1313

1414
/**
1515
* Enumerate loaders and their dependencies from this file to let the dependency validator

packages/@angular/cli/models/webpack-configs/styles.ts

+11-4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
} from '../../plugins/suppress-entry-chunks-webpack-plugin';
66
import { extraEntryParser, getOutputHashFormat } from './utils';
77
import { WebpackConfigOptions } from '../webpack-config';
8+
import { pluginArgs } from '../../tasks/eject';
89

910
const cssnano = require('cssnano');
1011
const autoprefixer = require('autoprefixer');
@@ -104,17 +105,23 @@ export function getStylesConfig(wco: WebpackConfigOptions) {
104105

105106
// load global css as css files
106107
if (globalStylePaths.length > 0) {
107-
rules.push(...baseRules.map(({test, loaders}) => ({
108-
include: globalStylePaths, test, loaders: ExtractTextPlugin.extract({
108+
rules.push(...baseRules.map(({test, loaders}) => {
109+
const extractTextPlugin = {
109110
use: [
110111
...commonLoaders,
111112
...loaders
112113
],
113114
fallback: 'style-loader',
114115
// publicPath needed as a workaround https://github.com/angular/angular-cli/issues/4035
115116
publicPath: ''
116-
})
117-
})));
117+
};
118+
const ret: any = {
119+
include: globalStylePaths, test, loaders: ExtractTextPlugin.extract(extractTextPlugin)
120+
};
121+
// Save the original options as arguments for eject.
122+
ret[pluginArgs] = extractTextPlugin;
123+
return ret;
124+
}));
118125
}
119126

120127
// supress empty .js files in css only entry points

packages/@angular/cli/models/webpack-configs/typescript.ts

+9-5
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ function _createAotPlugin(wco: WebpackConfigOptions, options: any) {
1616
const { appConfig, projectRoot, buildOptions } = wco;
1717

1818
// Read the environment, and set it in the compiler host.
19-
let hostOverrideFileSystem: any = {};
19+
let hostReplacementPaths: any = {};
2020
// process environment file replacement
2121
if (appConfig.environments) {
2222
if (!('source' in appConfig.environments)) {
@@ -29,9 +29,10 @@ function _createAotPlugin(wco: WebpackConfigOptions, options: any) {
2929
const appRoot = path.resolve(projectRoot, appConfig.root);
3030
const sourcePath = appConfig.environments['source'];
3131
const envFile = appConfig.environments[buildOptions.environment];
32-
const environmentContent = fs.readFileSync(path.join(appRoot, envFile)).toString();
3332

34-
hostOverrideFileSystem = { [path.join(appRoot, sourcePath)]: environmentContent };
33+
hostReplacementPaths = {
34+
[path.join(appRoot, sourcePath)]: path.join(appRoot, envFile)
35+
};
3536
}
3637

3738
return new AotPlugin(Object.assign({}, {
@@ -40,15 +41,18 @@ function _createAotPlugin(wco: WebpackConfigOptions, options: any) {
4041
i18nFile: buildOptions.i18nFile,
4142
i18nFormat: buildOptions.i18nFormat,
4243
locale: buildOptions.locale,
43-
hostOverrideFileSystem
44+
hostReplacementPaths
4445
}, options));
4546
}
4647

4748

4849
export const getNonAotConfig = function(wco: WebpackConfigOptions) {
4950
const { projectRoot, appConfig } = wco;
5051
let exclude = [ '**/*.spec.ts' ];
51-
if (appConfig.test) { exclude.push(path.join(projectRoot, appConfig.root, appConfig.test)); };
52+
if (appConfig.test) {
53+
exclude.push(path.join(projectRoot, appConfig.root, appConfig.test));
54+
}
55+
5256
return {
5357
module: {
5458
rules: [
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Exports the webpack plugins we use internally.
2+
3+
module.exports = {
4+
BaseHrefWebpackPlugin:
5+
require('../lib/base-href-webpack/base-href-webpack-plugin').BaseHrefWebpackPlugin,
6+
GlobCopyWebpackPlugin: require('../plugins/glob-copy-webpack-plugin').GlobCopyWebpackPlugin,
7+
SuppressExtractedTextChunksWebpackPlugin:
8+
require('../plugins/suppress-entry-chunks-webpack-plugin')
9+
.SuppressExtractedTextChunksWebpackPlugin
10+
};

0 commit comments

Comments
 (0)