UNPKG

8.35 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3const fs = require("fs");
4const path = require("path");
5const chalk = require("chalk");
6const rimraf = require("rimraf");
7const webpack = require("webpack");
8const url = require("url");
9const common_tags_1 = require("common-tags");
10const utils_1 = require("../models/webpack-configs/utils");
11const webpack_config_1 = require("../models/webpack-config");
12const config_1 = require("../models/config");
13const app_utils_1 = require("../utilities/app-utils");
14const WebpackDevServer = require('webpack-dev-server');
15const Task = require('../ember-cli/lib/models/task');
16const SilentError = require('silent-error');
17const opn = require('opn');
18exports.default = Task.extend({
19 run: function (serveTaskOptions, rebuildDoneCb) {
20 const ui = this.ui;
21 let webpackCompiler;
22 const projectConfig = config_1.CliConfig.fromProject().config;
23 const appConfig = app_utils_1.getAppFromConfig(projectConfig.apps, serveTaskOptions.app);
24 const outputPath = serveTaskOptions.outputPath || appConfig.outDir;
25 if (this.project.root === outputPath) {
26 throw new SilentError('Output path MUST not be project root directory!');
27 }
28 if (projectConfig.project && projectConfig.project.ejected) {
29 throw new SilentError('An ejected project cannot use the build command anymore.');
30 }
31 rimraf.sync(path.resolve(this.project.root, outputPath));
32 const serveDefaults = {
33 // default deployUrl to '' on serve to prevent the default from .angular-cli.json
34 deployUrl: ''
35 };
36 serveTaskOptions = Object.assign({}, serveDefaults, serveTaskOptions);
37 let webpackConfig = new webpack_config_1.NgCliWebpackConfig(serveTaskOptions, appConfig).buildConfig();
38 const serverAddress = url.format({
39 protocol: serveTaskOptions.ssl ? 'https' : 'http',
40 hostname: serveTaskOptions.host,
41 port: serveTaskOptions.port.toString()
42 });
43 let clientAddress = serverAddress;
44 if (serveTaskOptions.liveReloadClient) {
45 const clientUrl = url.parse(serveTaskOptions.liveReloadClient);
46 // very basic sanity check
47 if (!clientUrl.host) {
48 return Promise.reject(new SilentError(`'live-reload-client' must be a full URL.`));
49 }
50 clientAddress = clientUrl.href;
51 }
52 if (serveTaskOptions.liveReload) {
53 // This allows for live reload of page when changes are made to repo.
54 // https://webpack.github.io/docs/webpack-dev-server.html#inline-mode
55 let entryPoints = [
56 `webpack-dev-server/client?${clientAddress}`
57 ];
58 if (serveTaskOptions.hmr) {
59 const webpackHmrLink = 'https://webpack.github.io/docs/hot-module-replacement.html';
60 ui.writeLine(common_tags_1.oneLine `
61 ${chalk.yellow('NOTICE')} Hot Module Replacement (HMR) is enabled for the dev server.
62 `);
63 ui.writeLine(' The project will still live reload when HMR is enabled,');
64 ui.writeLine(' but to take advantage of HMR additional application code is required');
65 ui.writeLine(' (not included in an Angular CLI project by default).');
66 ui.writeLine(` See ${chalk.blue(webpackHmrLink)}`);
67 ui.writeLine(' for information on working with HMR for Webpack.');
68 entryPoints.push('webpack/hot/dev-server');
69 webpackConfig.plugins.push(new webpack.HotModuleReplacementPlugin());
70 webpackConfig.plugins.push(new webpack.NamedModulesPlugin());
71 if (serveTaskOptions.extractCss) {
72 ui.writeLine(common_tags_1.oneLine `
73 ${chalk.yellow('NOTICE')} (HMR) does not allow for CSS hot reload when used
74 together with '--extract-css'.
75 `);
76 }
77 }
78 if (!webpackConfig.entry.main) {
79 webpackConfig.entry.main = [];
80 }
81 webpackConfig.entry.main.unshift(...entryPoints);
82 }
83 else if (serveTaskOptions.hmr) {
84 ui.writeLine(chalk.yellow('Live reload is disabled. HMR option ignored.'));
85 }
86 if (!serveTaskOptions.watch) {
87 // There's no option to turn off file watching in webpack-dev-server, but
88 // we can override the file watcher instead.
89 webpackConfig.plugins.unshift({
90 apply: (compiler) => {
91 compiler.plugin('after-environment', () => {
92 compiler.watchFileSystem = { watch: () => { } };
93 });
94 }
95 });
96 }
97 webpackCompiler = webpack(webpackConfig);
98 if (rebuildDoneCb) {
99 webpackCompiler.plugin('done', rebuildDoneCb);
100 }
101 const statsConfig = utils_1.getWebpackStatsConfig(serveTaskOptions.verbose);
102 let proxyConfig = {};
103 if (serveTaskOptions.proxyConfig) {
104 const proxyPath = path.resolve(this.project.root, serveTaskOptions.proxyConfig);
105 if (fs.existsSync(proxyPath)) {
106 proxyConfig = require(proxyPath);
107 }
108 else {
109 const message = 'Proxy config file ' + proxyPath + ' does not exist.';
110 return Promise.reject(new SilentError(message));
111 }
112 }
113 let sslKey = null;
114 let sslCert = null;
115 if (serveTaskOptions.ssl) {
116 const keyPath = path.resolve(this.project.root, serveTaskOptions.sslKey);
117 if (fs.existsSync(keyPath)) {
118 sslKey = fs.readFileSync(keyPath, 'utf-8');
119 }
120 const certPath = path.resolve(this.project.root, serveTaskOptions.sslCert);
121 if (fs.existsSync(certPath)) {
122 sslCert = fs.readFileSync(certPath, 'utf-8');
123 }
124 }
125 const webpackDevServerConfiguration = {
126 headers: { 'Access-Control-Allow-Origin': '*' },
127 historyApiFallback: {
128 index: `/${appConfig.index}`,
129 disableDotRule: true,
130 htmlAcceptHeaders: ['text/html', 'application/xhtml+xml']
131 },
132 stats: statsConfig,
133 inline: true,
134 proxy: proxyConfig,
135 compress: serveTaskOptions.target === 'production',
136 watchOptions: {
137 poll: serveTaskOptions.poll
138 },
139 https: serveTaskOptions.ssl,
140 overlay: serveTaskOptions.target === 'development'
141 };
142 if (sslKey != null && sslCert != null) {
143 webpackDevServerConfiguration.key = sslKey;
144 webpackDevServerConfiguration.cert = sslCert;
145 }
146 webpackDevServerConfiguration.hot = serveTaskOptions.hmr;
147 if (serveTaskOptions.target === 'production') {
148 ui.writeLine(chalk.red(common_tags_1.stripIndents `
149 ****************************************************************************************
150 This is a simple server for use in testing or debugging Angular applications locally.
151 It hasn't been reviewed for security issues.
152
153 DON'T USE IT FOR PRODUCTION USE!
154 ****************************************************************************************
155 `));
156 }
157 ui.writeLine(chalk.green(common_tags_1.oneLine `
158 **
159 NG Live Development Server is running on ${serverAddress}
160 **
161 `));
162 const server = new WebpackDevServer(webpackCompiler, webpackDevServerConfiguration);
163 return new Promise((_resolve, reject) => {
164 server.listen(serveTaskOptions.port, serveTaskOptions.host, (err, _stats) => {
165 if (err) {
166 return reject(err);
167 }
168 if (serveTaskOptions.open) {
169 opn(serverAddress);
170 }
171 });
172 })
173 .catch((err) => {
174 if (err) {
175 this.ui.writeError('\nAn error occured during the build:\n' + ((err && err.stack) || err));
176 }
177 throw err;
178 });
179 }
180});
181//# sourceMappingURL=/users/hans/sources/angular-cli/tasks/serve.js.map
\No newline at end of file