-
Notifications
You must be signed in to change notification settings - Fork 467
/
webpack.config.js
143 lines (133 loc) · 5.32 KB
/
webpack.config.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
// Load the core node modules.
var AngularCompilerPlugin = require( "@ngtools/webpack" ).AngularCompilerPlugin;
var CleanWebpackPlugin = require( "clean-webpack-plugin" );
var HtmlWebpackPlugin = require( "html-webpack-plugin" );
var path = require( "path" );
var webpack = require( "webpack" );
// We are exporting a Function instead of a configuration object so that we can
// dynamically define the configuration object based on the execution mode.
module.exports = ( env, argv ) => {
var isDevelopmentMode = ( argv.mode === "development" );
// Locally, we want robust source-maps. However, in production, we want something
// that can help with debugging without giving away all of the source-code. This
// production setting will give us proper file-names and line-numbers for debugging;
// but, without actually providing any code content.
var devtool = isDevelopmentMode
? "eval-source-map"
: "nosources-source-map"
;
// By default, each module is identified based on Webpack's internal ordering. This
// can cause issues for cache-busting and long-term browser caching as a localized
// change can create a rippling effect on module identifiers. As such, we want to
// identify modules based on a name that is order-independent. Both of the following
// plugins do roughly the same thing; only, the one in development provides a longer
// and more clear ID.
var moduleIdentifierPlugin = isDevelopmentMode
? new webpack.NamedModulesPlugin()
: new webpack.HashedModuleIdsPlugin()
;
return({
// I define the base-bundles that will be generated.
// --
// NOTE: There is no explicit "vendor" bundle. With Webpack 4, that level of
// separation is handled by default. You just include your entry bundle and
// Webpack's splitChunks optimization DEFAULTS will automatically separate out
// modules that are in the "node_modules" folder.
entry: {
main: "./app/main.ts"
// NOTE: I'm currently including the polyfill directly in the main.ts file.
// If I have it as an Entry, I get a "cyclic dependency" error since I had to
// ALSO change my "chunksSortMode" to "none" in order to get Lazy Loading
// modules to work.
// --
// polyfill: "./app/main.polyfill.ts",
},
// I define the bundle file-name scheme.
output: {
filename: "[name].[contenthash].js",
path: path.join( __dirname, "build" ),
publicPath: "build/"
},
devtool: devtool,
resolve: {
extensions: [ ".ts", ".js" ],
alias: {
"~/app": path.resolve( __dirname, "app" )
}
},
module: {
rules: [
// I provide a TypeScript compiler that performs Ahead of Time (AoT)
// compilation for the Angular application and TypeScript code.
{
test: /(\.ngfactory\.js|\.ngstyle\.js|\.ts)$/,
loader: "@ngtools/webpack"
},
// When the @ngtools webpack loader runs, it will replace the @Component()
// "templateUrl" and "styleUrls" with inline "require()" calls. As such, we
// need the raw-loader so that require() will know how to load .htm and .css
// files as plain-text.
{
test: /\.(htm|css)$/,
loader: "raw-loader"
},
// If our components link to .less files instead of .css files, then the
// less-loader will parse the LESS CSS file on-the-fly during the require()
// call that is generated by the @ngtools webpack loader.
{
test: /\.less$/,
loaders: [
"raw-loader",
"less-loader"
]
}
]
},
plugins: [
// I clean the build directory before each build.
new CleanWebpackPlugin([
path.join( __dirname, "build/*.js" ),
path.join( __dirname, "build/*.js.map" )
]),
// I work with the @ngtools webpack loader to configure the Angular compiler.
new AngularCompilerPlugin({
tsConfigPath: path.join( __dirname, "tsconfig.json" ),
mainPath: path.join( __dirname, "app/main" ),
entryModule: path.join( __dirname, "app/app.module#AppModule" ),
// Webpack will generate source-maps independent of this setting. But,
// this setting uses the original source code in the source-map, rather
// than the generated / compiled code.
sourceMap: true
}),
// I generate the main "index" file and inject Script tags for the files emitted
// by the compilation process.
new HtmlWebpackPlugin({
// Notice that we are saving the index UP ONE DIRECTORY, so that it is output
// in the root of the demo.
filename: "../index.htm",
template: "./app/main.htm",
// CAUTION: I had to switch this to "none" when using Lazy Loading
// modules otherwise I was getting a "Cyclic dependency" error in the
// Toposort module in this plug-in. As a side-effect of this, I had to
// start including the Polyfill file directly in the main.ts (as opposed
// to including it as an entry point).
// --
// Read More: https://github.com/jantimon/html-webpack-plugin/issues/870
chunksSortMode: "none"
}),
// I facilitate better caching for generated bundles.
moduleIdentifierPlugin
],
optimization: {
splitChunks: {
// Apply optimizations to all chunks, even initial ones (not just the
// ones that are lazy-loaded).
chunks: "all"
},
// I pull the Webpack runtime out into its own bundle file so that the
// contentHash of each subsequent bundle will remain the same as long as the
// source code of said bundles remain the same.
runtimeChunk: "single"
}
});
};