Skip to content

Migration to Angular 6, RxJs 6 and Webpack 4 #2019

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
Jul 9, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ ___
# Angular Webpack Starter [![Join the chat at https://gitter.im/angularclass/angular2-webpack-starter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/angularclass/angular2-webpack-starter?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)


> An Angular starter kit featuring [Angular 5](https://angular.io), [Ahead of Time Compile](https://angular.io/docs/ts/latest/cookbook/aot-compiler.html), [Router](https://angular.io/docs/ts/latest/guide/router.html), [Forms](https://angular.io/docs/ts/latest/guide/forms.html),
> An Angular starter kit featuring [Angular 6](https://angular.io), [Ahead of Time Compile](https://angular.io/docs/ts/latest/cookbook/aot-compiler.html), [Router](https://angular.io/docs/ts/latest/guide/router.html), [Forms](https://angular.io/docs/ts/latest/guide/forms.html),
[Http](https://angular.io/docs/ts/latest/guide/server-communication.html),
[Services](https://gist.github.com/gdi2290/634101fec1671ee12b3e#_follow_@AngularClass_on_twitter),
[Tests](https://angular.io/docs/ts/latest/guide/testing.html), [E2E](https://angular.github.io/protractor/#/faq#what-s-the-difference-between-karma-and-protractor-when-do-i-use-which-)), [Karma](https://karma-runner.github.io/), [Protractor](https://angular.github.io/protractor/), [Jasmine](https://github.com/jasmine/jasmine), [Istanbul](https://github.com/gotwarlost/istanbul), [TypeScript](http://www.typescriptlang.org/), [@types](https://www.npmjs.com/~types), [TsLint](http://palantir.github.io/tslint/), [Codelyzer](https://github.com/mgechev/codelyzer), [Hot Module Replacement](https://webpack.github.io/docs/hot-module-replacement-with-webpack.html), and [Webpack](http://webpack.github.io/) by [Tipe](https://tipe.io).
Expand All @@ -32,7 +32,7 @@ ___
> If you're looking to learn TypeScript see [TypeStrong/learn-typescript](https://github.com/TypeStrong/learn-typescript)
> If you're looking for something easier to get started with then see the angular-seed that I also maintain [gdi2290/angular-seed](https://github.com/gdi2290/angular-seed)

This seed repo serves as an Angular starter for anyone looking to get up and running with Angular and TypeScript fast. Using a [Webpack 3](https://webpack.js.org) for building our files and assisting with boilerplate. We're also using Protractor for our end-to-end story and Karma for our unit tests.
This seed repo serves as an Angular starter for anyone looking to get up and running with Angular and TypeScript fast. Using a [Webpack 4](https://webpack.js.org) for building our files and assisting with boilerplate. We're also using Protractor for our end-to-end story and Karma for our unit tests.
* Best practices in file and application organization for Angular.
* Ready to go build system using Webpack for working with TypeScript.
* Angular examples that are ready to go when experimenting with Angular.
Expand Down
75 changes: 42 additions & 33 deletions config/html-elements-plugin/index.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,3 @@
function HtmlElementsPlugin(locations) {
this.locations = locations;
}

HtmlElementsPlugin.prototype.apply = function(compiler) {
var self = this;
compiler.plugin('compilation', function(compilation) {
compilation.options.htmlElements = compilation.options.htmlElements || {};

compilation.plugin('html-webpack-plugin-before-html-generation', function(htmlPluginData, callback) {
const locations = self.locations;

if (locations) {
const publicPath = htmlPluginData.assets.publicPath;

Object.getOwnPropertyNames(locations).forEach(function(loc) {
compilation.options.htmlElements[loc] = getHtmlElementString(locations[loc], publicPath);
});
}


callback(null, htmlPluginData);
});
});

};

const RE_ENDS_WITH_BS = /\/$/;

/**
Expand All @@ -49,8 +22,10 @@ function createTag(tagName, attrMap, publicPath) {
}

const attributes = Object.getOwnPropertyNames(attrMap)
.filter(function(name) { return name[0] !== '='; } )
.map(function(name) {
.filter(function (name) {
return name[0] !== '=';
})
.map(function (name) {
var value = attrMap[name];

if (publicPath) {
Expand Down Expand Up @@ -98,16 +73,50 @@ function createTag(tagName, attrMap, publicPath) {
*/
function getHtmlElementString(dataSource, publicPath) {
return Object.getOwnPropertyNames(dataSource)
.map(function(name) {
.map(function (name) {
if (Array.isArray(dataSource[name])) {
return dataSource[name].map(function(attrs) { return createTag(name, attrs, publicPath); } );
return dataSource[name].map(function (attrs) {
return createTag(name, attrs, publicPath);
});
} else {
return [ createTag(name, dataSource[name], publicPath) ];
return [createTag(name, dataSource[name], publicPath)];
}
})
.reduce(function(arr, curr) {
.reduce(function (arr, curr) {
return arr.concat(curr);
}, [])
.join('\n\t');
}

class HtmlElementsPlugin {
constructor(locations) {
this.locations = locations;
}

/* istanbul ignore next: this would be integration tests */
apply(compiler) {
compiler.hooks.compilation.tap('HtmlElementsPlugin', compilation => {
compilation.options.htmlElements = compilation.options.htmlElements || {};
compilation.hooks.htmlWebpackPluginBeforeHtmlGeneration.tapAsync('HtmlElementsPlugin',
(htmlPluginData, callback) => {

const locations = this.locations;
if (locations) {
const publicPath = htmlPluginData.assets.publicPath;

Object.getOwnPropertyNames(locations).forEach(function (loc) {

compilation.options.htmlElements[loc] = getHtmlElementString(locations[loc], publicPath);
});
}

// return htmlPluginData;
callback(null, htmlPluginData);
}
);
});
}
}

module.exports = HtmlElementsPlugin;

9 changes: 7 additions & 2 deletions config/karma.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ module.exports = function (config) {
/**
* enable / disable watching file and executing tests whenever any file changes
*/
autoWatch: false,
autoWatch: true,

/**
* start these browsers
Expand All @@ -134,7 +134,12 @@ module.exports = function (config) {
* Continuous Integration mode
* if true, Karma captures browsers, runs the tests and exits
*/
singleRun: true,
singleRun: false,

client: {
clearContext: false // leave Jasmine Spec Runner output visible in browser
},

/**
* For slower machines you may need to have a longer browser
* wait time . Uncomment the line below if required.
Expand Down
5 changes: 0 additions & 5 deletions config/spec-bundle.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,6 @@ require('zone.js/dist/jasmine-patch'); // put here since zone.js 0.6.14
require('zone.js/dist/async-test');
require('zone.js/dist/fake-async-test');

/**
* RxJS
*/
require('rxjs/Rx');

var testing = require('@angular/core/testing');
var browser = require('@angular/platform-browser-dynamic/testing');

Expand Down
88 changes: 25 additions & 63 deletions config/webpack.common.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,12 @@ const helpers = require('./helpers');
* problem with copy-webpack-plugin
*/
const DefinePlugin = require('webpack/lib/DefinePlugin');
const CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const HtmlElementsPlugin = require('./html-elements-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const WebpackInlineManifestPlugin = require('webpack-inline-manifest-plugin');
const LoaderOptionsPlugin = require('webpack/lib/LoaderOptionsPlugin');
const ScriptExtHtmlWebpackPlugin = require('script-ext-html-webpack-plugin');
const ngcWebpack = require('ngc-webpack');
const AngularCompilerPlugin = require('@ngtools/webpack').AngularCompilerPlugin;

const buildUtils = require('./build-utils');

Expand All @@ -26,19 +24,19 @@ const buildUtils = require('./build-utils');
*
* See: https://webpack.js.org/configuration/
*/
module.exports = function (options) {
module.exports = function(options) {
const isProd = options.env === 'production';
const APP_CONFIG = require(process.env.ANGULAR_CONF_FILE || (isProd ? './config.prod.json' : './config.dev.json'));

const METADATA = Object.assign({}, buildUtils.DEFAULT_METADATA,options.metadata || {});
const METADATA = Object.assign({}, buildUtils.DEFAULT_METADATA, options.metadata || {});
const GTM_API_KEY = process.env.GTM_API_KEY || APP_CONFIG.gtmKey;

const ngcWebpackConfig = buildUtils.ngcWebpackSetup(isProd, METADATA);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why don't you delete this line? I thought you replaced ngcwebpack with ngtoolswebpack

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The config is still used, though. ngcWebpack is just a wrapper around webpack/ngtools and almost all config values are the same.

Copy link
Contributor Author

@lanovoy lanovoy Jul 9, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might want to do some renaming here for clarity...

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks!

const supportES2015 = buildUtils.supportES2015(METADATA.tsConfigPath);

const entry = {
polyfills: './src/polyfills.browser.ts',
main: './src/main.browser.ts'
main: './src/main.browser.ts'
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't these 2 paths start with '../src/' because webpack.common.js is in config folder?

};

Object.assign(ngcWebpackConfig.plugin, {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose the path is relative to the folder in which node process for webpack is getting launched from, so that would be the root with package.json - not /config...

Expand All @@ -61,7 +59,7 @@ module.exports = function (options) {
* See: https://webpack.js.org/configuration/resolve/
*/
resolve: {
mainFields: [ ...(supportES2015 ? ['es2015'] : []), 'browser', 'module', 'main' ],
mainFields: [...(supportES2015 ? ['es2015'] : []), 'browser', 'module', 'main'],

/**
* An array of extensions that should be used to resolve modules.
Expand Down Expand Up @@ -103,7 +101,6 @@ module.exports = function (options) {
* See: https://webpack.js.org/configuration/module/
*/
module: {

rules: [
...ngcWebpackConfig.loaders,

Expand Down Expand Up @@ -155,9 +152,7 @@ module.exports = function (options) {
test: /\.(eot|woff2?|svg|ttf)([\?]?.*)$/,
use: 'file-loader'
}

],

]
},

/**
Expand All @@ -177,40 +172,15 @@ module.exports = function (options) {
*/
// NOTE: when adding more properties make sure you include them in custom-typings.d.ts
new DefinePlugin({
'ENV': JSON.stringify(METADATA.ENV),
'HMR': METADATA.HMR,
'AOT': METADATA.AOT,
ENV: JSON.stringify(METADATA.ENV),
HMR: METADATA.HMR,
AOT: METADATA.AOT,
'process.env.ENV': JSON.stringify(METADATA.ENV),
'process.env.NODE_ENV': JSON.stringify(METADATA.ENV),
'process.env.HMR': METADATA.HMR,
'process.env.HMR': METADATA.HMR
// 'FIREBASE_CONFIG': JSON.stringify(APP_CONFIG.firebase),
}),

/**
* Plugin: CommonsChunkPlugin
* Description: Shares common code between the pages.
* It identifies common modules and put them into a commons chunk.
*
* See: https://webpack.js.org/plugins/commons-chunk-plugin/
* See: https://github.com/webpack/docs/wiki/optimization#multi-page-app
*/
new CommonsChunkPlugin({
name: 'polyfills',
chunks: ['polyfills']
}),

new CommonsChunkPlugin({
minChunks: Infinity,
name: 'inline'
}),
new CommonsChunkPlugin({
name: 'main',
async: 'common',
children: true,
minChunks: 2
}),


/**
* Plugin: CopyWebpackPlugin
* Description: Copy files and directories in webpack.
Expand All @@ -219,11 +189,9 @@ module.exports = function (options) {
*
* See: https://www.npmjs.com/package/copy-webpack-plugin
*/
new CopyWebpackPlugin([
{ from: 'src/assets', to: 'assets' },
{ from: 'src/meta'}
],
isProd ? { ignore: [ 'mock-data/**/*' ] } : undefined
new CopyWebpackPlugin(
[{ from: 'src/assets', to: 'assets' }, { from: 'src/meta' }],
isProd ? { ignore: ['mock-data/**/*'] } : undefined
),

/*
Expand All @@ -237,22 +205,24 @@ module.exports = function (options) {
new HtmlWebpackPlugin({
template: 'src/index.html',
title: METADATA.title,
chunksSortMode: function (a, b) {
const entryPoints = ["inline","polyfills","sw-register","styles","vendor","main"];
chunksSortMode: function(a, b) {
const entryPoints = ['inline', 'polyfills', 'sw-register', 'styles', 'vendor', 'main'];
return entryPoints.indexOf(a.names[0]) - entryPoints.indexOf(b.names[0]);
},
metadata: METADATA,
gtmKey: GTM_API_KEY,
inject: 'body',
xhtml: true,
minify: isProd ? {
caseSensitive: true,
collapseWhitespace: true,
keepClosingSlash: true
} : false
minify: isProd
? {
caseSensitive: true,
collapseWhitespace: true,
keepClosingSlash: true
}
: false
}),

/**
/**
* Plugin: ScriptExtHtmlWebpackPlugin
* Description: Enhances html-webpack-plugin functionality
* with different deployment options for your scripts including:
Expand Down Expand Up @@ -292,22 +262,15 @@ module.exports = function (options) {
headTags: require('./head-config.common')
}),

/**
* Plugin LoaderOptionsPlugin (experimental)
*
* See: https://gist.github.com/sokra/27b24881210b56bbaff7
*/
new LoaderOptionsPlugin({}),

new ngcWebpack.NgcWebpackPlugin(ngcWebpackConfig.plugin),
new AngularCompilerPlugin(ngcWebpackConfig.plugin),

/**
* Plugin: WebpackInlineManifestPlugin
* Inline Webpack's manifest.js in index.html
*
* https://github.com/almothafar/webpack-inline-manifest-plugin
*/
new WebpackInlineManifestPlugin(),
new WebpackInlineManifestPlugin()
],

/**
Expand All @@ -324,6 +287,5 @@ module.exports = function (options) {
clearImmediate: false,
setImmediate: false
}

};
};
Loading