Skip to content

Commit ef1655b

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 a22474e commit ef1655b

35 files changed

+705
-59
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,
+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { BuildOptions } from '../models/build-options';
2+
import { Version } from '../upgrade/version';
3+
import {baseBuildCommandOptions} from './build';
4+
5+
const Command = require('../ember-cli/lib/models/command');
6+
7+
// defaults for BuildOptions
8+
export const baseEjectCommandOptions: any = [
9+
...baseBuildCommandOptions,
10+
{ name: 'force', 'type': Boolean }
11+
];
12+
13+
export interface EjectTaskOptions extends BuildOptions {
14+
force?: boolean;
15+
}
16+
17+
18+
const EjectCommand = Command.extend({
19+
name: 'eject',
20+
description: 'Ejects your app and output the proper webpack configuration and scripts.',
21+
22+
availableOptions: baseEjectCommandOptions,
23+
24+
run: function (commandOptions: EjectTaskOptions) {
25+
const project = this.project;
26+
const EjectTask = require('../tasks/eject').default;
27+
const ejectTask = new EjectTask({
28+
cliProject: project,
29+
ui: this.ui,
30+
});
31+
32+
return ejectTask.run(commandOptions);
33+
}
34+
});
35+
36+
37+
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

+5
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@
1313
},
1414
"name": {
1515
"type": "string"
16+
},
17+
"ejected": {
18+
"description": "Whether or not this project was ejected.",
19+
"type": "boolean",
20+
"default": false
1621
}
1722
},
1823
"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
@@ -17,7 +17,7 @@ function _createAotPlugin(wco: WebpackConfigOptions, options: any) {
1717
const { appConfig, projectRoot, buildOptions } = wco;
1818

1919
// Read the environment, and set it in the compiler host.
20-
let hostOverrideFileSystem: any = {};
20+
let hostReplacementPaths: any = {};
2121
// process environment file replacement
2222
if (appConfig.environments) {
2323
if (!appConfig.environmentSource) {
@@ -58,9 +58,10 @@ function _createAotPlugin(wco: WebpackConfigOptions, options: any) {
5858
const appRoot = path.resolve(projectRoot, appConfig.root);
5959
const sourcePath = appConfig.environmentSource;
6060
const envFile = appConfig.environments[buildOptions.environment];
61-
const environmentContent = fs.readFileSync(path.join(appRoot, envFile)).toString();
6261

63-
hostOverrideFileSystem = { [path.join(appRoot, sourcePath)]: environmentContent };
62+
hostReplacementPaths = {
63+
[path.join(appRoot, sourcePath)]: path.join(appRoot, envFile)
64+
};
6465
}
6566

6667
return new AotPlugin(Object.assign({}, {
@@ -69,15 +70,18 @@ function _createAotPlugin(wco: WebpackConfigOptions, options: any) {
6970
i18nFile: buildOptions.i18nFile,
7071
i18nFormat: buildOptions.i18nFormat,
7172
locale: buildOptions.locale,
72-
hostOverrideFileSystem
73+
hostReplacementPaths
7374
}, options));
7475
}
7576

7677

7778
export const getNonAotConfig = function(wco: WebpackConfigOptions) {
7879
const { projectRoot, appConfig } = wco;
7980
let exclude = [ '**/*.spec.ts' ];
80-
if (appConfig.test) { exclude.push(path.join(projectRoot, appConfig.root, appConfig.test)); };
81+
if (appConfig.test) {
82+
exclude.push(path.join(projectRoot, appConfig.root, appConfig.test));
83+
}
84+
8185
return {
8286
module: {
8387
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)