angular webpack stater 代码程序解析 - Christian-Yang/Translate-and-save GitHub Wiki
这页代码是对angular2-webpack-starter的源代码的解析,源代码在https://github.com/AngularClass/angular2-webpack-starter。
这是webpack里面的插件的官方的列表:https://webpack.github.io/docs/list-of-plugins.html
在JavaScript的世界里,有两个词经常被提到,shim和polyfill.它们指的都是什么,又有什么区别?
一个shim是一个库,它将一个新的API引入到一个旧的环境中,而且仅靠旧环境中已有的手段实现
一个polyfill就是一个用在浏览器API上的shim.我们通常的做法是先检查当前浏览器是否支持某个API,如果不支持的话就加载对应的polyfill.然后新旧浏览器就都可以使用这个API了.术语polyfill来自于一个家装产品Polyfilla:
Polyfilla是一个英国产品,在美国称之为Spackling Paste(译者注:刮墙的,在中国称为腻子).记住这一点就行:把旧的浏览器想象成为一面有了裂缝的墙.这些[polyfills]会帮助我们把这面墙的裂缝抹平,还我们一个更好的光滑的墙壁(浏览器)
Paul Irish发布过一个Polyfills的总结页面“HTML5 Cross Browser Polyfills”.es5-shim是一个shim(而不是polyfill)的例子,它在ECMAScript 3的引擎上实现了ECMAScript 5的新特性,而且在Node.js上和在浏览器上有完全相同的表现(译者注:因为它能在Node.js上使用,不光浏览器上,所以它不是polyfill).
//html-elements-plugin/index.js
//html-elements-plugin/index.js
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 = /\/$/;
/**
* Create an HTML tag with attributes from a map.
*
* Example:
* createTag('link', { rel: "manifest", href: "/assets/manifest.json" })
* // <link rel="manifest" href="/assets/manifest.json">
* @param tagName The name of the tag
* @param attrMap A Map of attribute names (keys) and their values.
* @param publicPath a path to add to eh start of static asset url
* @returns {string}
*使用地图中的属性创建一个HTML标签。
*
*示例:
* createTag('link',{rel:“manifest”,href:“/assets/manifest.json”})
* // <link rel =“manifest”href =“/ assets / manifest.json”>
* @param tagName标签的名称
* @param attrMap属性名称(键)及其值的映射。
* @param publicPath将静态资源网址添加到eh开头的路径
* @returns {string}
这个函数的作用就是:输入createTag('link', { rel: "manifest", href: "/assets/manifest.json" })返回
<link rel="manifest" href="/assets/manifest.json">
如果给publicPath传递参数,比如传递"sssssss",那么最终形成的路径就会改变,变成在/assets前面加上"sssssss"
C:\nodework>node yang.js
<link rel="manifest" href="sssssss/assets/manifest.json">
C:\nodework>node yang.js
<link rel="manifest" href="/assets/manifest.json">
*/
function createTag(tagName, attrMap, publicPath) {
publicPath = publicPath || '';
// add trailing slash if we have a publicPath and it doesn't have one.
if (publicPath && !RE_ENDS_WITH_BS.test(publicPath)) {
publicPath += '/';
}
const attributes = Object.getOwnPropertyNames(attrMap)
.filter(function(name) { return name[0] !== '='; } )
.map(function(name) {
var value = attrMap[name];
if (publicPath) {
// check if we have explicit instruction, use it if so (e.g: =herf: false)
// if no instruction, use public path if it's href attribute.
const usePublicPath = attrMap.hasOwnProperty('=' + name) ? !!attrMap['=' + name] : name === 'href';
if (usePublicPath) {
// remove a starting trailing slash if the value has one so we wont have //
value = publicPath + (value[0] === '/' ? value.substr(1) : value);
}
}
return `${name}="${value}"`;
});
const closingTag = tagName === 'script' ? '</script>' : '';
return `<${tagName} ${attributes.join(' ')}>${closingTag}`;
}
/**
* Returns a string representing all html elements defined in a data source.
*
* Example:
*
* const ds = {
* link: [
* { rel: "apple-touch-icon", sizes: "57x57", href: "/assets/icon/apple-icon-57x57.png" }
* ],
* meta: [
* { name: "msapplication-TileColor", content: "#00bcd4" }
* ]
* }
*
* getHtmlElementString(ds);
* // "<link rel="apple-touch-icon" sizes="57x57" href="/assets/icon/apple-icon-57x57.png">"
* "<meta name="msapplication-TileColor" content="#00bcd4">"
*
* @returns {string}
* 这个函数的作用就是输入一个ds这样的东西返回
* <link rel="apple-touch-icon" sizes="57x57" href="/assets/icon/apple-icon-57x57.png">
* <meta name="msapplication-TileColor" content="#00bcd4">
*/
function getHtmlElementString(dataSource, publicPath) {
return Object.getOwnPropertyNames(dataSource)
.map(function(name) {
if (Array.isArray(dataSource[name])) {
return dataSource[name].map(function(attrs) { return createTag(name, attrs, publicPath); } );
} else {
return [ createTag(name, dataSource[name], publicPath) ];
}
})
.reduce(function(arr, curr) {
return arr.concat(curr);
}, [])
.join('\n\t');
}
module.exports = HtmlElementsPlugin;
//helpers.js
//helpers.js
/**
* @author: @AngularClass
*/
var path = require('path');
/*
npm 提供一个npm_lifecycle_event变量,返回当前正在运行的脚本名称,比如pretest、test、posttest等等。
所以,可以利用这个变量,在同一个脚本文件里面,为不同的npm scripts命令编写代码
*/
const EVENT = process.env.npm_lifecycle_event || '';
// Helper functions
/*在任何模块文件内部,可以使用__dirname变量获取当前模块文件所在目录的完整绝对路径。
path.resolve([from ...], to)
由于该方法属于path模块,使用前需要引入path模块(var path= require(“path”) )
path.resolve('/foo/bar', './baz')
// returns
'/foo/bar/baz'
path.resolve('/foo/bar', '/tmp/file/')
// returns
'/tmp/file'
path.resolve('wwwroot', 'static_files/png/', '../gif/image.gif')
// if currently in /home/myself/node, it returns
'/home/myself/node/wwwroot/static_files/gif/image.gif'
*/
//返回当前目录的上一级目录
var ROOT = path.resolve(__dirname, '..');
/*
process.argv (一个包含命令行参数的数组。
第一个元素是’node’,第二个元素是JavaScript文件的文件名。接下来的元素则是附加的命令行参数。)
node yang.js --color
join() 方法用于把数组中的所有元素放入一个字符串。
有进程标志? 这个函数的作用就是用来查看有没有指定的参数
*/
function hasProcessFlag(flag) {
return process.argv.join('').indexOf(flag) > -1;
}
/*
includes() 方法用来判断当前数组是否包含某指定的值,如果是,则返回 true,否则返回 false。
*/
function hasNpmFlag(flag) {
return EVENT.includes(flag);
}
/*
*/
function isWebpackDevServer() {
/*
windows下写了个脚本js,名字叫做yang.js,然后运行输出
console.log('process.argv[1]',process.argv[1]);
console.log('!! (/webpack-dev-server/.exec(process.argv[1]))',!! (/ya/.exec(process.argv[1])));
第一个运行的时候输出: process.argv[1] C:\nodework\yang.js
第二个运行的时候输出:true。第二个这个实际上是一个正则表达式
查询在process.argv[1]中有没有ya这个字符串将。
所以也就是在C:\nodework\yang.js中查找有没有ya这个字符串。如果有的话,那么就返回true
*/
return process.argv[1] && !! (/webpack-dev-server/.exec(process.argv[1]));
}
/*
格式化路径 path.normalize(p)
特点:将不符合规范的路径格式化,简化开发人员中处理各种复杂的路径判断
示例:
path.normalize('/foo/bar//baz/asdf/quux/..');
// returns
'/foo/bar/baz/asdf'
路径联合 path.join([path1], [path2], [...])
特点:将所有名称用path.seq串联起来,然后用normailze格式化
path.join('///foo', 'bar', '//baz/asdf', 'quux', '..');
// returns
'/foo/bar/baz/asdf
bind()方法会创建一个新函数,称为绑定函数,当调用这个绑定函数时,
绑定函数会以创建它时传入 bind()方法的第一个参数作为 this,
传入 bind() 方法的第二个以及以后的参数加上绑定函数运行
时本身的参数按照顺序作为原函数的参数来调用原函数。
注意path和ROOT前面已经定义过了
(2)这个bind函数应该是,JavaScript中bind函数,这个函数用来创建一个新函数
最终var root = path.join.bind(path, ROOT);这个函数什么意思看不太懂,
但是这个东西是一个函数,这个函数传递一个参数root('dist'),那么就会在生成一个
新目录,比如我在:C:\nodeWork> 运行这个函数,并且传递了一个dist参数,
那么就会生成一个C:\dists目录。
这个函数的意思就是使用上级目录为根目录,创建新的目录将来。
*/
var root = path.join.bind(path, ROOT);
exports.hasProcessFlag = hasProcessFlag;
exports.hasNpmFlag = hasNpmFlag;
exports.isWebpackDevServer = isWebpackDevServer;
exports.root = root;
//webpack.common.js
/**
* @author: @AngularClass
*/
const webpack = require('webpack');
const helpers = require('./helpers');
/*
* Webpack Plugins
*/
// problem with copy-webpack-plugin
/*
assets-webpack-plugin
使用资源路径发布json文件的Webpack插件。
使用Webpack时,您可能希望在其中生成包含生成的散列(用于缓存清除)。
这个插件输出一个json文件与生成的资源的路径,所以你可以从别的地方找到它们。
就是说一个源文件和一个生成的文件之间通过json进行映射。
*/
const AssetsPlugin = require('assets-webpack-plugin');
/*
http://www.css88.com/doc/webpack2/plugins/normal-module-replacement-plugin/
NormalModuleReplacementPlugin 是 webpack 一个内置插件。
NormalModuleReplacementPlugin允许您将与resourceRegExp匹配的资源替换为newResource。
如果newResource是相对的,它相对于先前的资源被解析。
如果newResource是一个函数,则期望覆盖所提供的资源的请求属性。
这对于允许构建之间的不同行为是有用的。
在构建开发环境时更换特定模块(了解更多)。
如果说你有一个配置文件some/path/config.development.module.js
和一个特殊的版本生产在some/path/config.production.module.js
只需在构建生产时添加以下插件:
new webpack.NormalModuleReplacementPlugin(
【注意下面的路径被进行转义字符替换之后,就变成了/some/path/config.development.js/】
/some\/path\/config\.development\.js/,
'./config.production.js'
);
所以这个插件的意思就是把/some/path/config.development.js/替换成为'./config.production.js'
*/
const NormalModuleReplacementPlugin = require('webpack/lib/NormalModuleReplacementPlugin');
/*
*/
const ContextReplacementPlugin = require('webpack/lib/ContextReplacementPlugin');
/*
http://www.cnblogs.com/vajoy/p/4650467.html
这里我们使用了一个 CommonsChunkPlugin 的插件,
它用于提取多个入口文件的公共脚本部分,然后生成一个 common.js 来方便多页面之间进行复用
*/
const CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin');
/*
http://www.cnblogs.com/grimm/p/5772444.html
4. 拷贝资源插件
copy-webpack-plugin
官方这样解释 Copy files and directories in webpack,在webpack中拷贝文件和文件夹
cnpm install --save-dev copy-webpack-plugin
new CopyWebpackPlugin([{
from: __dirname + '/src/public'
}]),
作用:把public 里面的内容全部拷贝到编译目录
参数 作用 其他说明
from 定义要拷贝的源目录 from: __dirname + '/src/public'
to 定义要烤盘膛的目标目录 from: __dirname + '/dist'
toType file 或者 dir 可选,默认是文件
force 强制覆盖先前的插件 可选 默认false
context 不知道作用 可选 默认 base context 可用 specific context
flatten[扁平化] 只拷贝文件不管文件夹 默认是false
ignore 忽略拷贝指定的文件 可以用模糊匹配
*/
const CopyWebpackPlugin = require('copy-webpack-plugin');
/*
awesome-typescript-loader - 一个用于把TypeScript代码转译成ES5的加载器,
它会由tsconfig.json文件提供指导
https://angular.cn/docs/ts/latest/guide/webpack.html
*/
const CheckerPlugin = require('awesome-typescript-loader').CheckerPlugin;
/*
注意这个是html-elements-plugin目录下面的index.js文件
*/
const HtmlElementsPlugin = require('./html-elements-plugin');
/*
http://www.cnblogs.com/haogj/p/5160821.html
这个插件用来简化创建服务于 webpack bundle 的 HTML 文件,尤其是对于在文件名中包含了 hash 值,
而这个值在每次编译的时候都发生变化的情况。你既可以让这个插件来帮助你
自动生成 HTML 文件,也可以使用 lodash 模板加载生成的 bundles,或者自己加载这些 bundles。
这个插件可以帮助生成 HTML 文件,在 body 元素中,使用 script 来包含所有你的 webpack bundles,
只需要在你的 webpack 配置文件中如下配置:
*/
const HtmlWebpackPlugin = require('html-webpack-plugin');
/*
http://www.css88.com/doc/webpack2/plugins/loader-options-plugin/
loader-options-plugin 和其他插件不同。它的用途是帮助人们从 webpack 1 迁移至 webpack 2。在 webpack 2 中对 webpack.config.js 的结构要求变得更加严格;不再开放扩展给其他的加载器/插件。webpack 2 推荐的使用方式是直接传递 options 给加载器/插件。换句话说,配置选项将不是全局/共享的。
不过,在某个加载器升级为依靠直接传递给它的配置选项运行之前,可以使用 loader-options-plugin 来抹平差异。你可以通过这个插件配置全局/共享的加载器配置,使所有的加载器都能收到这些配置。
在将来这个插件可能会被移除
*/
const LoaderOptionsPlugin = require('webpack/lib/LoaderOptionsPlugin');
/*
https://github.com/kossnocorp/assets-webpack-plugin
增强html-webpack-plugin功能,使用不同的脚本部署选项,包括:
异步属性
延迟属性
type =“module”属性;
内联
预加载资源提示;
预取资源提示
这是一个用于webpack插件的扩展插件html-webpack-plugin - 一个插件,可以简化HTML文件的创建,
以便为您的Webpack包提供服务。
原始的html-webpack-plugin将所有webpack生成的javascipt作为生成的html中的同步<script>元素。
此插件允许您:
添加这些元素的属性;
内联代码中的元素;
为初始和动态加载的脚本添加预取和预加载资源提示
*/
const ScriptExtHtmlWebpackPlugin = require('script-ext-html-webpack-plugin');
/*
ngc-webpack
@angular / compiler-cli Webpack包装器
命令行界面(Command Line Interface)
https://github.com/shlomiassaf/ngc-webpack
这个东西具体是什么不太清楚,看不懂,但是意思就是用来编译angular的,因为
@angular/compiler-cli这个东西就是一个angular的编译器。这里就是把这个东西给
封装了一下然后给webpack用
*/
const ngcWebpack = require('ngc-webpack');
/**/
/*
* Webpack Constants
webpack定义的常量
*/
/*
hasProcessFlag函数作用:
process.argv (一个包含命令行参数的数组。
第一个元素是’node’,第二个元素是JavaScript文件的文件名。接下来的元素则是附加的命令行参数。)
node yang.js --color
join() 方法用于把数组中的所有元素放入一个字符串。
有进程标志? 这个函数的作用就是用来查看有没有指定的参数
function hasProcessFlag(flag) {
return process.argv.join('').indexOf(flag) > -1;
}
*/
//运行命令的时候是否有hot附加参数,如果有表示这个“热模块替换”
const HMR = helpers.hasProcessFlag('hot');
/*
/*
npm 提供一个npm_lifecycle_event变量,返回当前正在运行的脚本名称,
比如pretest、test、posttest等等。
所以,可以利用这个变量,在同一个脚本文件里面,为不同的npm scripts命令编写代码
const EVENT = process.env.npm_lifecycle_event || '';
function hasNpmFlag(flag) {
return EVENT.includes(flag);
}
看看当前运行的脚本名字中是否有aot标志,有就表示预编译
https://angular.cn/docs/ts/latest/cookbook/aot-compiler.html#!#aot-jit
*/
const AOT = helpers.hasNpmFlag('aot');
/*
*/
const METADATA = {
title: 'Angular2 Webpack Starter by @gdi2290 from @AngularClass',
baseUrl: '/',
/*
process.argv
一个包含命令行参数的数组。第一个元素为 'node',第二个元素为 JavaScript 文件名。剩下的参数为附加的命令行参数。
1 // print process.argv
2 process.argv.forEach(function(val, index, array) {
3 console.log(index + ': ' + val);
4 });
输出将会是:
$ node process-2.js one two=three four
0: node
1: /User/mjr/work/node/process-2.js
2: one
3: two=three
4: four
*/
isDevServer: helpers.isWebpackDevServer()
};
/*
* Webpack configuration
*
* See: http://webpack.github.io/docs/configuration.html#cli
*/
module.exports = function (options) {
//判断是否是prod环境
isProd = options.env === 'production';
return {
/*
* Cache generated modules and chunks to improve performance for multiple incremental builds.
* This is enabled by default in watch mode.
* You can pass false to disable it.
* 缓存生成的模块和块,以提高多个增量版本的性能。
* 默认情况下,在watch模式下启用。
* 你可以传递false来禁用它。
* See: http://webpack.github.io/docs/configuration.html#cache
*/
//cache: false,
/*
* The entry point for the bundle
* Our Angular.js app
*
* See: http://webpack.github.io/docs/configuration.html#entry
*/
entry: {
//【这里应该需要配置】
'polyfills': './src/polyfills.browser.ts',
'main': AOT ? './src/main.browser.aot.ts' :
'./src/main.browser.ts'
},
/*
* Options affecting the resolving of modules.
* 影响模块解决的选项。
* See: http://webpack.github.io/docs/configuration.html#resolve
按照 webpack 官方的说法,resolve配置用来影响webpack模块解析规则。
解析规则也可以称之为检索,索引规则。配置索引规则能够缩短webpack的解析时间,提升打包速度。
先说几个问题:
resolve.root 用来配置搜索路径集合。root配置必须是绝对路径,不能存在./app/modules之类的相对路径。
resolve.modulesDirectory 是指需要向上搜索的目录名称(即如果当前目录找不到,找上级目录),
一般只会是node_modules之类的。其他自定义的资源一般不需要向上搜索,可以配置alias
root和modulesDirectory 在[email protected]中被舍弃了,使用了新的规则resolve.modules,这是前两者的结合体
resolveLoader相当于是针对webpack Loader 的单独 resolve 配置,做用和resolve一样,但只作用于webpack loader
*/
resolve: {
/*
* An array of extensions that should be used to resolve modules.
* 应用于解析模块的扩展数组。
* See: http://webpack.github.io/docs/configuration.html#resolve-extensions
*/
extensions: ['.ts', '.js', '.json'],
// An array of directory names to be resolved to the current directory
//要解析到当前目录的目录名称数组
//【这里应该需要配置】 配置了源代码目录和node_modules目录
modules: [helpers.root('src'), helpers.root('node_modules')],
},
/*
* Options affecting the normal modules.
* 影响正常模块的选项。
* See: http://webpack.github.io/docs/configuration.html#module
*/
module: {
rules: [
/*
* Typescript loader support for .ts
* 用于支持.ts的Typescript loader
* Component Template/Style integration using `angular2-template-loader`
* 使用“angular2-template-loader”组件模板/样式集成
* Angular 2 lazy loading (async routes) via `ng-router-loader`
* Angular 2懒加载(异步路由)通过`ng-router-loader'
* `ng-router-loader` expects vanilla JavaScript code, not TypeScript code. This is why the
* order of the loader matter.
* ng-router-loader`需要使用vanilla JavaScript代码,
* 而不是TypeScript代码。 这就是为什么装载机的顺序很重要
* See: https://github.com/s-panferov/awesome-typescript-loader
* See: https://github.com/TheLarkInn/angular2-template-loader
* See: https://github.com/shlomiassaf/ng-router-loader
*/
{
test: /\.ts$/,
use: [
{
loader: '@angularclass/hmr-loader',
options: {
pretty: !isProd,
prod: isProd
}
},
{ // MAKE SURE TO CHAIN VANILLA JS CODE, I.E. TS COMPILATION OUTPUT.
loader: 'ng-router-loader',
options: {
loader: 'async-import',
genDir: 'compiled',
aot: AOT
}
},
{
loader: 'awesome-typescript-loader',
/*【这里可能需要配置,这个是配置当编译的时候,ts编译规则,比如把一个
ts文件翻译成为什么样子的js文件。这个不是lint检查的那个,这个只是用来配置
翻译】*/
options: {
configFileName: 'tsconfig.webpack.json'
}
},
{
loader: 'angular2-template-loader'
}
],
exclude: [/\.(spec|e2e)\.ts$/]
},
/*
* Json loader support for *.json files.
* Json loader支持* .json文件。
* See: https://github.com/webpack/json-loader
*/
{
test: /\.json$/,
use: 'json-loader'
},
/*
* to string and css loader support for *.css files (from Angular components)
to string和css loader支持* .css文件(从Angular组件)
* Returns file content as string
*
*/
{
test: /\.css$/,
use: ['to-string-loader', 'css-loader'],
exclude: [helpers.root('src', 'styles')]
},
/*
* to string and sass loader support for *.scss files (from Angular components)
* to string和sass loader支持* .scss文件(从angular组件)
* Returns compiled css content as string
* 返回编译的CSS内容作为字符串
*/
{
test: /\.scss$/,
use: ['to-string-loader', 'css-loader', 'sass-loader'],
exclude: [helpers.root('src', 'styles')]
},
/* Raw loader support for *.html
* Returns file content as string
*
* See: https://github.com/webpack/raw-loader
*原始loader支持* .html
*将文件内容作为字符串返回
*
*请参阅:https://github.com/webpack/raw-loader
*/
{
test: /\.html$/,
use: 'raw-loader',
exclude: [helpers.root('src/index.html')]
},
/*
* File loader for supporting images, for example, in CSS files.
* 用于支持图像的文件加载器,例如,在CSS文件中。
*/
{
test: /\.(jpg|png|gif)$/,
use: 'file-loader'
},
/*
* File loader for supporting fonts, for example, in CSS files.
* 用于支持字体的文件加载器,例如,在CSS文件中。
*/
{
test: /\.(eot|woff2?|svg|ttf)([\?]?.*)$/,
use: 'file-loader'
}
],
},
/*
* Add additional plugins to the compiler.
* 向编译器添加额外的插件。
* See: http://webpack.github.io/docs/configuration.html#plugins
*/
plugins: [
new AssetsPlugin({
//【这里需要配置】
/*
Optional. Defaults to the current directory.Path where to save the created JSON file.
可选的.默认当前目录,路径用来保存创建的json文件。
*/
path: helpers.root('dist'),
filename: 'webpack-assets.json',
prettyPrint: true
}),
/*
* Plugin: ForkCheckerPlugin
* Description: Do type checking in a separate process, so webpack don't need to wait.
* 插件:ForkCheckerPlugin 说明:在单独的进程中进行类型检查,因此Webpack不需要等待
* See: https://github.com/s-panferov/awesome-typescript-loader#forkchecker-boolean-defaultfalse
*/
new CheckerPlugin(),
/*
* Plugin: CommonsChunkPlugin
* Description: Shares common code between the pages.
* It identifies common modules and put them into a commons chunk.
* 插件:CommonsChunkPlugin
说明:共享页面之间的通用代码。
它识别常见的模块并将它们放入公共块中。
* See: https://webpack.github.io/docs/list-of-plugins.html#commonschunkplugin
* See: https://github.com/webpack/docs/wiki/optimization#multi-page-app
*/
new CommonsChunkPlugin({
name: 'polyfills',
chunks: ['polyfills']
}),
// This enables tree shaking of the vendor modules
//这使得供应商模块的树状抖动
new CommonsChunkPlugin({
name: 'vendor',
chunks: ['main'],
minChunks: module => /node_modules/.test(module.resource)
}),
// Specify the correct order the scripts will be injected in
//指定脚本将被注入的正确顺序
new CommonsChunkPlugin({
name: ['polyfills', 'vendor'].reverse()
}),
/**
* Plugin: ContextReplacementPlugin
* Description: Provides context to Angular's use of System.import
* 插件:ContextReplacementPlugin
* 说明:提供angular使用System.import的上下文
* See: https://webpack.github.io/docs/list-of-plugins.html#contextreplacementplugin
* See: https://github.com/angular/angular/issues/11580
这个git的issue您需要为Angular使用System.import提供上下文。System.import应该是SystemJs中的一个API
================================================================================================
* https://wohugb.gitbooks.io/webpack/content/LISTS/list_of_plugins.html
new webpack.ContextReplacementPlugin(
resourceRegExp,
[newContentResource],
[newContentRecursive],
[newContentRegExp])
Replaces the default resource, recursive flag or regExp generated by parsing with newContentResource,
newContentRecursive resp. newContextRegExp if the resource (directory) matches resourceRegExp.
If newContentResource is relative, it is resolve relative to the previous resource.
If newContentResource is a function,it is expected to overwrite the 'request' attribute of the supplied object.
*/
new ContextReplacementPlugin(
// The (\\|\/) piece accounts for path separators in *nix and Windows
/angular(\\|\/)core(\\|\/)src(\\|\/)linker/,
//【这里需要配置】
helpers.root('src'), // location of your src
{
// your Angular Async Route paths relative to this root directory
//您的Angular Async Route路径相对于此根目录
}
),
/*
* Plugin: CopyWebpackPlugin
* Description: Copy files and directories in webpack.
*
* Copies project static assets.
* 复制webpack中的文件和目录。 复制项目静态资产。
* See: https://www.npmjs.com/package/copy-webpack-plugin
*/
new CopyWebpackPlugin([
//【这里需要配置,注意这里assets目录下包括很多的东西】
{ from: 'src/assets', to: 'assets' },
{ from: 'src/meta'}
]),
/*
* Plugin: HtmlWebpackPlugin
* Description: Simplifies creation of HTML files to serve your webpack bundles.
* This is especially useful for webpack bundles that include a hash in the filename
* which changes every compilation.
* 插件:HtmlWebpackPlugin
说明:简化HTML文件的创建,为您的Webpack捆绑提供服务。
这对于包含更改每个编译的文件名中的哈希的webpack bundle尤其有用。
* See: https://github.com/ampedandwired/html-webpack-plugin
*/
new HtmlWebpackPlugin({
template: 'src/index.html',
title: METADATA.title,
chunksSortMode: 'dependency',
metadata: METADATA,
inject: 'head'
}),
/*
* Plugin: ScriptExtHtmlWebpackPlugin
* Description: Enhances html-webpack-plugin functionality
* with different deployment options for your scripts including:
* 插件:ScriptExtHtmlWebpackPlugin
说明:增强html-webpack-plugin功能
为您的脚本提供不同的部署选项,包括:
* See: https://github.com/numical/script-ext-html-webpack-plugin
*/
new ScriptExtHtmlWebpackPlugin({
defaultAttribute: 'defer'
}),
/*
* Plugin: HtmlElementsPlugin
* Description: Generate html tags based on javascript maps.
*
* If a publicPath is set in the webpack output configuration, it will be automatically added to
* href attributes, you can disable that by adding a "=href": false property.
* You can also enable it to other attribute by settings "=attName": true.
*
* The configuration supplied is map between a location (key) and an element definition object (value)
* The location (key) is then exported to the template under then htmlElements property in webpack configuration.
*
* Example:
* Adding this plugin configuration
* new HtmlElementsPlugin({
* headTags: { ... }
* })
*
* Means we can use it in the template like this:
* <%= webpackConfig.htmlElements.headTags %>
*
* Dependencies: HtmlWebpackPlugin
插件:HtmlElementsPlugin
说明:根据javascript map生成html标签。
如果在webpack输出配置中设置了一个publicPath,它将被自动添加到
href属性,可以通过添加“= href”:false属性来禁用该属性。
您也可以通过设置“= attName”将其设置为其他属性:true。
提供的配置是位置(键)和元素定义对象(值)之间的映射
然后将位置(键)导出到webpack中的htmlElements属性下的模板
例:
添加此插件配置
新的HtmlElementsPlugin({
headTags:{...}
})
意味着我们可以在模板中使用它:
<%= webpackConfig.htmlElements.headTags%>
依赖关系:HtmlWebpackPlugin
这个插件是自己写的在html-elements-plugin这个文件中,这个东西的作用就是把输入的东西
添加到最终的形成的整个系统的index.html页面中。比如这里传递进来的是head-config.common.js
这个文件,那么最终就会把这个文件里面的link或者meta的东西,全部添加到index.html页面中。
*/
new HtmlElementsPlugin({
headTags: require('./head-config.common')
}),
/**
* Plugin LoaderOptionsPlugin (experimental)
* 插件LoaderOptionsPlugin(实验)
* See: https://gist.github.com/sokra/27b24881210b56bbaff7
*/
new LoaderOptionsPlugin({}),
// Fix Angular 2
new NormalModuleReplacementPlugin(
/facade(\\|\/)async/,
helpers.root('node_modules/@angular/core/src/facade/async.js')
),
new NormalModuleReplacementPlugin(
/facade(\\|\/)collection/,
helpers.root('node_modules/@angular/core/src/facade/collection.js')
),
new NormalModuleReplacementPlugin(
/facade(\\|\/)errors/,
helpers.root('node_modules/@angular/core/src/facade/errors.js')
),
new NormalModuleReplacementPlugin(
/facade(\\|\/)lang/,
helpers.root('node_modules/@angular/core/src/facade/lang.js')
),
new NormalModuleReplacementPlugin(
/facade(\\|\/)math/,
helpers.root('node_modules/@angular/core/src/facade/math.js')
),
new ngcWebpack.NgcWebpackPlugin({
disabled: !AOT,
tsConfig: helpers.root('tsconfig.webpack.json'),
resourceOverride: helpers.root('config/resource-override.js')
})
],
/*
* Include polyfills or mocks for various node stuff
* Description: Node configuration
* 包括用于各种node的聚合物或模拟物
说明:node配置
* See: https://webpack.github.io/docs/configuration.html#node
*/
node: {
global: true,
crypto: 'empty',
process: true,
module: false,
clearImmediate: false,
setImmediate: false
}
};
}
//webpack.dev.js
//webpack.dev.js
/**
* @author: @AngularClass
*/
const helpers = require('./helpers');
/*
used to merge webpack configs
用于合并webpack配置
*/
const webpackMerge = require('webpack-merge');
/*
https://github.com/survivejs/webpack-merge/issues/17
在Webpack中的插件顺序很重要。 这意味着第一个匹配的插件获胜。
目前,webpack-merge按照它们找到的顺序连接数组。
所以如果你有合并(common,prod),那么它将从普通的第一个和prod之后接收插件。
这个东西类似于json中的重复key的问题,也就是说在webpack中如果出现了两个
相同的配置那么该怎么办?取哪个?先前的,后面的。
*/
const webpackMergeDll = webpackMerge.strategy({plugins: 'replace'});
// the settings that are common to prod and dev prod和dev公用的东西
const commonConfig = require('./webpack.common.js');
/**
* Webpack Plugins
*/
/*
Add a JavaScript or CSS asset to the HTML generated by html-webpack-plugin
向html-webpack-plugin生成的HTML文件中添加javascript文件或者css文件。
https://github.com/simenb/add-asset-html-webpack-plugin
*/
const AddAssetHtmlPlugin = require('add-asset-html-webpack-plugin');
/*
https://github.com/webpack/docs/wiki/list-of-plugins
http://www.css88.com/doc/webpack2/plugins/define-plugin/
允许你创建一个在编译时可以配置的全局常量。
这可能会对开发模式和发布模式的构建允许不同的行为非常有用。
比如,你可能会用一个全局的常量来决定 log 在开发模式触发而不是发布模式。
这仅仅是 DefinePlugin 提供的便利的一个场景。
*/
const DefinePlugin = require('webpack/lib/DefinePlugin');
/*
NamedModulesPlugin
这个模块可以将依赖模块的正整数 ID 替换为相对路径
(如:将 4 替换为 ./node_modules/es6-promise/dist/es6-promise.js)。
开发模式,它可以让 webpack-dev-server 和 HMR 进行热更新时在控制台输出模块名字而不是纯数字;
生产构建环境,它可以避免因修改内容导致的 ID 变化,从而实现持久化缓存。
但是有两个缺点:
递增 ID 替换为模块相对路径,构建出来的 chunk 会充满各种路径,使文件增大;
模块(npm 和自己的模块)路径会泄露,可能导致安全问题。
*/
const NamedModulesPlugin = require('webpack/lib/NamedModulesPlugin');
/*
loader-options-plugin 和其他插件不同。它的用途是帮助人们从 webpack 1 迁移至 webpack 2。
在 webpack 2 中对 webpack.config.js 的结构要求变得更加严格;不再开放扩展给其他的加载器/插件。
webpack 2 推荐的使用方式是直接传递 options 给加载器/插件。换句话说,配置选项将不是全局/共享的。
不过,在某个加载器升级为依靠直接传递给它的配置选项运行之前,可以使用 loader-options-plugin 来抹平差异。
你可以通过这个插件配置全局/共享的加载器配置,使所有的加载器都能收到这些配置。
在将来这个插件可能会被移除。
http://www.css88.com/doc/webpack2/plugins/loader-options-plugin/
这个插件的意思就是,webpack1是支持配置选项是全局/共享的,也就是说你在全局配置了一个
东西,这个东西对每个插件或者加载器都有效。但是在webpack2中为了结构的严格,不在支持
全局配置了。但是为了达到能全局配置的效果,那么就可以使用这个插件。这样这个插件配置的
每个项目,就可以在每个加载器或者插件中都有效。
*/
const LoaderOptionsPlugin = require('webpack/lib/LoaderOptionsPlugin');
/**
* Webpack Constants
*/
//传递'development'参数,这样就知道是开发模式
const ENV = process.env.ENV = process.env.NODE_ENV = 'development';
//设置ip
const HOST = process.env.HOST || 'localhost';
//设置端口
const PORT = process.env.PORT || 3000;
//启动热模块替换
const HMR = helpers.hasProcessFlag('hot');
/*
因为从webpack.common.js中导入了这个commonConfig所以这个东西就是一个函数
这个函数有一个参数这个参数就是options,所以相当于给commonConfig中,也就是
commonConfig中传递了一个{env:ENV}字段。
把commonConfig中的元数据和当前文件中的元数据合并,然后创建一个新的METADATA
*/
const METADATA = webpackMerge(commonConfig({env: ENV}).metadata, {
host: HOST,
port: PORT,
ENV: ENV,
HMR: HMR
});
/*
一个用于将软件包组捆绑为DLL的Webpack插件
Webpack的一个插件,使用Webpack的DllPlugin和DllReferencePlugin作为构建过程的一部分来创建捆绑包配置。
该插件将监视软件包中的更改并相应地重新构建软件包。
https://github.com/shlomiassaf/webpack-dll-bundles-pluginenv
*/
const DllBundlesPlugin = require('webpack-dll-bundles-plugin').DllBundlesPlugin;
/**
* Webpack configuration
*
* See: http://webpack.github.io/docs/configuration.html#cli
*/
module.exports = function (options) {
/*
webpackMerge这里合并了两个function对象,一个是commonConfig({env:ENV})
另外一个是后面的那个参数。
*/
return webpackMerge(commonConfig({env: ENV}), {
/**
* Developer tool to enhance debugging
*
* See: http://webpack.github.io/docs/configuration.html#devtool
* See: https://github.com/webpack/docs/wiki/build-performance#sourcemaps
用来进行source map的配置。
*/
devtool: 'cheap-module-source-map',
/**
* Options affecting the output of the compilation.
* 影响编译输出的选项。
* See: http://webpack.github.io/docs/configuration.html#output
*/
output: {
/**
* The output directory as absolute path (required).
* 输出目录为绝对路径(必填)。
* See: http://webpack.github.io/docs/configuration.html#output-path
*/
path: helpers.root('dist'),
/**
* Specifies the name of each output file on disk.
* IMPORTANT: You must not specify an absolute path here!
* 指定磁盘上每个输出文件的名称。 重要:您不能在此指定绝对路径!
* See: http://webpack.github.io/docs/configuration.html#output-filename
*/
filename: '[name].bundle.js',
/**
* The filename of the SourceMaps for the JavaScript files.
JavaScript文件的SourceMaps的文件名。
* They are inside the output.path directory.
它们在output.path目录中。
* See: http://webpack.github.io/docs/configuration.html#output-sourcemapfilename
*/
sourceMapFilename: '[file].map',
/** The filename of non-entry chunks as relative path
* inside the output.path directory.
* [non-entry]块的文件名作为output.path目录中的相对路径。
* 非入口文件的那些文件的输出文件名字,也就是说在entry{}中不存在的那些文件的文件名字
* See: http://webpack.github.io/docs/configuration.html#output-chunkfilename
*/
chunkFilename: '[id].chunk.js',
/*如果设置了这个选项,会将bundle导出为library。 output.library是library的名字
如果你正在编写library,并且需要将其发布为单独的文件,请使用此选项*/
library: 'ac_[name]',
/*
library的导出格式:
"var" 导出为一个变量: var liobrary = xxx (默认)
如果output.library没有设置,但是output.libraryTarget被设置为var以外的值,则[所导出的对象]的每个属性
都被复制到[对应的被导出对象]上(除了amd,commonjs2和umd)
*/
libraryTarget: 'var',
},
module: {
rules: [
{
test: /\.ts$/,
use: [
{
loader: 'tslint-loader',
options: {
configFile: 'tslint.json'
}
}
],
exclude: [/\.(spec|e2e)\.ts$/]
},
/*
* css loader support for *.css files (styles directory only)
* Loads external css styles into the DOM, supports HMR
* css加载器支持* .css文件(仅限样式目录)将外部CSS样式加载到DOM中,支持HMR
*/
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
include: [helpers.root('src', 'styles')]
},
/*
* sass loader support for *.scss files (styles directory only)
* Loads external sass styles into the DOM, supports HMR
* sass loader支持* .scss文件(仅限样式目录)将外部sass样式加载到DOM中,支持HMR
*/
{
test: /\.scss$/,
use: ['style-loader', 'css-loader', 'sass-loader'],
include: [helpers.root('src', 'styles')]
},
]
},
plugins: [
/**
* Plugin: DefinePlugin
* Description: Define free variables.
* Useful for having development builds with debug logging or adding global constants.
*
* Environment helpers
*
* See: https://webpack.github.io/docs/list-of-plugins.html#defineplugin
NOTE: when adding more properties, make sure you include them in custom-typings.d.ts
*插件:DefinePlugin
*说明:定义自由变量。
*对于通过调试日志记录或添加全局常量进行开发构建非常有用。
*
*环境帮手
*
*见https://webpack.github.io/docs/list-of-plugins.html#defineplugin
注意:添加更多属性时,请确保将它们包含在custom-typings.d.ts中
*/
new DefinePlugin({
'ENV': JSON.stringify(METADATA.ENV),
'HMR': METADATA.HMR,
'process.env': {
'ENV': JSON.stringify(METADATA.ENV),
'NODE_ENV': JSON.stringify(METADATA.ENV),
'HMR': METADATA.HMR,
}
}),
new DllBundlesPlugin({
bundles: {
polyfills: [
'core-js',
{
name: 'zone.js',
path: 'zone.js/dist/zone.js'
},
{
name: 'zone.js',
path: 'zone.js/dist/long-stack-trace-zone.js'
},
],
vendor: [
'@angular/platform-browser',
'@angular/platform-browser-dynamic',
'@angular/core',
'@angular/common',
'@angular/forms',
'@angular/http',
'@angular/router',
'@angularclass/hmr',
'rxjs',
]
},
dllDir: helpers.root('dll'),
webpackConfig: webpackMergeDll(commonConfig({env: ENV}), {
devtool: 'cheap-module-source-map',
plugins: []
})
}),
/**
* Plugin: AddAssetHtmlPlugin
* Description: Adds the given JS or CSS file to the files
* Webpack knows about, and put it into the list of assets
* html-webpack-plugin injects into the generated html.
* 插件:AddAssetHtmlPlugin
说明:将给定的JS或CSS文件添加到文件中
Webpack了解并将其放入资产清单中
html-webpack-plugin注入生成的html。
请参阅:https://github.com/SimenB/add-asset-html-webpack-plugin
* See: https://github.com/SimenB/add-asset-html-webpack-plugin
*/
/*https://github.com/shlomiassaf/webpack-dll-bundles-plugin
注意 上一行的git上有我们通过48行代码:
const DllBundlesPlugin = require('webpack-dll-bundles-plugin').DllBundlesPlugin;
让js可以向Dll一样,那么怎么样使用这个dll还在48行代码的插件,那个页面上就有
*/
new AddAssetHtmlPlugin([
{ filepath: helpers.root(`dll/${DllBundlesPlugin.resolveFile('polyfills')}`) },
{ filepath: helpers.root(`dll/${DllBundlesPlugin.resolveFile('vendor')}`) }
]),
/**
* Plugin: NamedModulesPlugin (experimental)
* Description: Uses file names as module name.
*
* See: https://github.com/webpack/webpack/commit/a04ffb928365b19feb75087c63f13cadfc08e1eb
new NamedModulesPlugin(),
插件:NamedModulesPlugin(实验)
说明:使用文件名作为模块名称。
请参阅:https://github.com/webpack/webpack/commit/a04ffb928365b19feb75087c63f13cadfc08e1eb
新的NamedModulesPlugin(),
插件LoaderOptionsPlugin(实验)
请参阅:https://gist.github.com/sokra/27b24881210b56bbaff7
* Plugin LoaderOptionsPlugin (experimental)
* See: https://gist.github.com/sokra/27b24881210b56bbaff7
*/
new LoaderOptionsPlugin({
debug: true,
options: {
}
}),
],
/**
* Webpack Development Server configuration
* Description: The webpack-dev-server is a little node.js Express server.
* The server emits information about the compilation state to the client,
* which reacts to those events.
Webpack开发服务器配置
说明:webpack-dev-server是一个小的node.js Express服务器。
服务器向客户端发送有关编译状态的信息,
它们对这些事件做出了反应。
请参阅:https://webpack.github.io/docs/webpack-dev-server.html
* See: https://webpack.github.io/docs/webpack-dev-server.html
*/
devServer: {
port: METADATA.port,
host: METADATA.host,
//如果历史回退之后找不到页面那么就显示404
historyApiFallback: true,
watchOptions: {
aggregateTimeout: 300,
poll: 1000
}
},
/*
* Include polyfills or mocks for various node stuff
* Description: Node configuration
* 全局配置node
* See: https://webpack.github.io/docs/configuration.html#node
*/
node: {
global: true,
crypto: 'empty',
process: true,
module: false,
clearImmediate: false,
setImmediate: false
}
});
}
//webpack.prod.js
/**
* @author: @AngularClass
*/
const helpers = require('./helpers');
// used to merge webpack configs
const webpackMerge = require('webpack-merge');
// the settings that are common to prod and dev
const commonConfig = require('./webpack.common.js');
/**
* Webpack Plugins
*/
/*
https://github.com/webpack/docs/wiki/list-of-plugins
http://www.css88.com/doc/webpack2/plugins/define-plugin/
允许你创建一个在编译时可以配置的全局常量。
这可能会对开发模式和发布模式的构建允许不同的行为非常有用。
比如,你可能会用一个全局的常量来决定 log 在开发模式触发而不是发布模式。
这仅仅是 DefinePlugin 提供的便利的一个场景。
*/
const DefinePlugin = require('webpack/lib/DefinePlugin');
/*
extract-text-webpack-plugin该插件的主要是为了抽离css样式,
防止将样式打包在js中引起页面样式加载错乱的现象;
http://www.cnblogs.com/dyx-wx/p/6529447.html
*/
const ExtractTextPlugin = require('extract-text-webpack-plugin');
/*
IgnorePlugin
new webpack.IgnorePlugin(requestRegExp, [contextRegExp])
Don’t generate modules for requests matching the provided RegExp.
【requestRegExp】 A RegExp to test the request against.
【contextRegExp】 (optional) A RegExp to test the context (directory) against.
IgnorePlugin
新的webpack.IgnorePlugin(requestRegExp,[contextRegExp])
如果请求匹配requestRegExp这个正则表达式,那么不要产生模块
【requestRegExp】一个RegExp来测试请求。
【contextRegExp】(可选)用于测试上下文(目录)的RegExp。
*/
const IgnorePlugin = require('webpack/lib/IgnorePlugin');
/*
loader-options-plugin 和其他插件不同。它的用途是帮助人们从 webpack 1 迁移至 webpack 2。
在 webpack 2 中对 webpack.config.js 的结构要求变得更加严格;不再开放扩展给其他的加载器/插件。
webpack 2 推荐的使用方式是直接传递 options 给加载器/插件。换句话说,配置选项将不是全局/共享的。
不过,在某个加载器升级为依靠直接传递给它的配置选项运行之前,可以使用 loader-options-plugin 来抹平差异。
你可以通过这个插件配置全局/共享的加载器配置,使所有的加载器都能收到这些配置。
在将来这个插件可能会被移除。
http://www.css88.com/doc/webpack2/plugins/loader-options-plugin/
这个插件的意思就是,webpack1是支持配置选项是全局/共享的,也就是说你在全局配置了一个
东西,这个东西对每个插件或者加载器都有效。但是在webpack2中为了结构的严格,不在支持
全局配置了。但是为了达到能全局配置的效果,那么就可以使用这个插件。这样这个插件配置的
每个项目,就可以在每个加载器或者插件中都有效。
*/
const LoaderOptionsPlugin = require('webpack/lib/LoaderOptionsPlugin');
/*
http://www.css88.com/doc/webpack2/plugins/normal-module-replacement-plugin/
NormalModuleReplacementPlugin 是 webpack 一个内置插件。
NormalModuleReplacementPlugin允许您将与resourceRegExp匹配的资源替换为newResource。
如果newResource是相对的,它相对于先前的资源被解析。
如果newResource是一个函数,则期望覆盖所提供的资源的请求属性。
这对于允许构建之间的不同行为是有用的。
在构建开发环境时更换特定模块(了解更多)。
如果说你有一个配置文件some/path/config.development.module.js
和一个特殊的版本生产在some/path/config.production.module.js
只需在构建生产时添加以下插件:
new webpack.NormalModuleReplacementPlugin(
【注意下面的路径被进行转义字符替换之后,就变成了/some/path/config.development.js/】
/some\/path\/config\.development\.js/,
'./config.production.js'
);
所以这个插件的意思就是把/some/path/config.development.js/替换成为'./config.production.js'
*/
const NormalModuleReplacementPlugin = require('webpack/lib/NormalModuleReplacementPlugin');
/*
ProvidePlugin 可以让变量直接在模块里加载而不需要使用 require 等方法。
所以我们可以预先定义一些模块根据不同的环境装载不同的模块:
//development.js
module.exports = { baseUrl: 'http://dev.api.xx.com' };
//production.js
module.exports = { baseUrl: 'http://api.xx.com' };
//test.js
module.exports = { baseUrl: 'http://test.api.xx.com' };
//webpack.config.js
var webpack = require("webpack");
module.exports = {
entry: "main.js",
output: {path: "./", filename: "bundle.js"},
plugins: [
new webpack.ProvidePlugin({
ENV: "./env/"+ (process.env.NODE_ENV || "development")
})
]
};
然后我们在环境变量中定义 NODE_ENV 变量帮助 node 识别环境,例如:
//Windows
set NODE_ENV=test
//Linux or OSX
export NODE_ENV=test
这样在 webpack 编译的时候就能判别出是 test 环境使用 test 的环境变量了,我们直接在代码中使用 ENV.baseUrl 即可。
http://www.tuicool.com/articles/nMf6Vv7
webpack提供一个插件 把一个全局变量插入到所有的代码中,在config.js里面配置
https://zhuanlan.zhihu.com/p/20397902?columnSlug=FrontendMagazine
*/
const ProvidePlugin = require('webpack/lib/ProvidePlugin');
/*
https://segmentfault.com/a/1190000003506497
丑化js
*/
const UglifyJsPlugin = require('webpack/lib/optimize/UglifyJsPlugin');
/*
optimize-js-plugin这个插件实际上是对optimize-js这个插件的一个包装。
optimize-js这个插件的作用是:通过将所有立即调用的函数或可能被调用的函数包含
在括号中来优化JavaScript文件以便更快的初始执行和解析。
https://github.com/nolanlawson/optimize-js
optimize-js-plugin
Webpack插件通过包装【eagerly-invoked 】功能来优化JavaScript文件以加快初始加载速度。
See: https://github.com/vigneshshanmugam/optimize-js-plugin
*/
const OptimizeJsPlugin = require('optimize-js-plugin');
/**
* Webpack Constants
*/
/*
process.env属性返回一个包含用户环境的对象。也就是说用户的环境变量。
这个东西是可以往里面添加东西,比如我可以写process.env.yang="yang"
那么环境变量里面就添加了一个key=yang;value="yang"
那么下面的代码的意思是:给process.env中添加NODE_ENV和ENV这两个环境变量
并且赋值'production'。
*/
const ENV = process.env.NODE_ENV = process.env.ENV = 'production';
/*
下面的意思是如果有环境变量process.env.HOST那么就使用这个,否则使用localhost
如果有process.env.PORT那么就使用这个变量,否则就使用8080
*/
const HOST = process.env.HOST || 'localhost';
const PORT = process.env.PORT || 8080;
const METADATA = webpackMerge(commonConfig({
env: ENV
}).metadata, {
host: HOST,
port: PORT,
ENV: ENV,
HMR: false
});
module.exports = function (env) {
return webpackMerge(commonConfig({
env: ENV
}), {
/**
* Developer tool to enhance debugging
* source-map原来代码映射
* See: http://webpack.github.io/docs/configuration.html#devtool
* See: https://github.com/webpack/docs/wiki/build-performance#sourcemaps
*/
devtool: 'source-map',
/**
* Options affecting the output of the compilation.
*
* See: http://webpack.github.io/docs/configuration.html#output
*/
output: {
/**
* The output directory as absolute path (required).
* 输出目录为绝对路径(必填)。
* See: http://webpack.github.io/docs/configuration.html#output-path
* 当前目录的上级目录下的dist
*/
path: helpers.root('dist'),
/**
* Specifies the name of each output file on disk.
* IMPORTANT: You must not specify an absolute path here!
* 指定磁盘上每个输出文件的名称。
* 重要:您不能在此指定绝对路径!
* See: http://webpack.github.io/docs/configuration.html#output-filename
*/
filename: '[name].[chunkhash].bundle.js',
/**
* The filename of the SourceMaps for the JavaScript files.
* They are inside the output.path directory.
* JavaScript文件的SourceMaps的文件名。
* 它们位于output.path目录中。
* See: http://webpack.github.io/docs/configuration.html#output-sourcemapfilename
*/
sourceMapFilename: '[name].[chunkhash].bundle.map',
/**
* The filename of non-entry chunks as relative path
* inside the output.path directory.
* non-entry块的文件名作为output.path目录中的相对路径。
* See: http://webpack.github.io/docs/configuration.html#output-chunkfilename
*/
chunkFilename: '[id].[chunkhash].chunk.js'
},
module: {
rules: [
/*
* Extract CSS files from .src/styles directory to external CSS file
* 将CSS文件从.src / styles目录提取到外部CSS文件
*/
{
test: /\.css$/,
loader: ExtractTextPlugin.extract({
//fallback:编译后用什么loader来提取css文件
fallback: 'style-loader',
//use:指需要什么样的loader去编译文件,这里由于源文件是.css所以选择css-loader
use: 'css-loader'
}),
/*
var path = require('path');
var ROOT = path.resolve(__dirname, '..');
console.log(ROOT)
var root = path.join.bind(path, ROOT);
console.log(root)
console.log(root('src', 'styles'));
C:\nodework>node yang.js
C:\
[Function: bound join]
C:\src\styles
这里就能看出来意思就是:在当前目录的上级目录下面的src/styles目录
包括src/styles目录
*/
include: [helpers.root('src', 'styles')]
},
/*
* Extract and compile SCSS files from .src/styles directory to external CSS file
提取并且编译.src/styles目录下的scss文件到外部的css文件
*/
{
test: /\.scss$/,
loader: ExtractTextPlugin.extract({
//fallback:编译后用什么loader来提取css文件
fallback: 'style-loader',
/*use:指需要什么样的loader去编译文件,这里由于源文件是sass所以选择sass-loader
和css-loader,因为这个东西是从右向左运行的,所以先是使用sass-loader然后使用css-loader*/
use: 'css-loader!sass-loader'
}),
//src/styles目录
include: [helpers.root('src', 'styles')]
},
]
},
/**
* Add additional plugins to the compiler.
* 向编译器添加额外的插件。
* See: http://webpack.github.io/docs/configuration.html#plugins
*/
plugins: [
/**
* Webpack plugin to optimize a JavaScript file for faster initial load
* by wrapping eagerly-invoked functions.
* Webpack插件通过包装【eagerly-invoked 】功能来优化JavaScript文件以加快初始加载速度。
* See: https://github.com/vigneshshanmugam/optimize-js-plugin
*/
new OptimizeJsPlugin({
sourceMap: false
}),
/**
* Plugin: ExtractTextPlugin
* Description: Extracts imported CSS files into external stylesheet
* 插件:ExtractTextPlugin说明:将导入的CSS文件提取到外部样式表中
* See: https://github.com/webpack/extract-text-webpack-plugin
*/
new ExtractTextPlugin('[name].[contenthash].css'),
/**
* Plugin: DefinePlugin
* Description: Define free variables.
* Useful for having development builds with debug logging or adding global constants.
*插件:DefinePlugin
*说明:定义自由变量。
*对于通过调试日志记录或添加全局常量进行开发构建非常有用。
* Environment helpers
*
* See: https://webpack.github.io/docs/list-of-plugins.html#defineplugin
*/
// 注意:添加更多属性时,请确保将它们包含在custom-typings.d.ts中
// 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,
'process.env': {
'ENV': JSON.stringify(METADATA.ENV),
'NODE_ENV': JSON.stringify(METADATA.ENV),
'HMR': METADATA.HMR,
}
}),
/**
* Plugin: UglifyJsPlugin
* Description: Minimize all JavaScript output of chunks.
* Loaders are switched into minimizing mode.
* 说明:最小化所有JavaScript输出的块。
Loaders切换到最小化模式。
* See: https://webpack.github.io/docs/list-of-plugins.html#uglifyjsplugin
*/
//注意:调试prod builds取消注释//调试行和注释// prod行
// NOTE: To debug prod builds uncomment //debug lines and comment //prod lines
new UglifyJsPlugin({
// beautify: true, //debug
// mangle: false, //debug
// dead_code: false, //debug
// unused: false, //debug
// deadCode: false, //debug
// compress: {
// screw_ie8: true,
// keep_fnames: true,
// drop_debugger: false,
// dead_code: false,
// unused: false
// }, // debug
// comments: true, //debug
beautify: false, //prod
output: {
comments: false
}, //prod
mangle: {
screw_ie8: true
}, //prod
compress: {
screw_ie8: true,
warnings: false,
conditionals: true,
unused: true,
comparisons: true,
sequences: true,
dead_code: true,
evaluate: true,
if_return: true,
join_vars: true,
negate_iife: false // we need this for lazy v8
},
}),
/**
* Plugin: NormalModuleReplacementPlugin
* Description: Replace resources that matches resourceRegExp with newResource
* 插件:NormalModuleReplacementPlugin
* 说明:将resourceRegExp匹配的资源替换为newResource
* See: http://webpack.github.io/docs/list-of-plugins.html#normalmodulereplacementplugin
*/
new NormalModuleReplacementPlugin(
/angular2-hmr/,
helpers.root('config/empty.js')
),
new NormalModuleReplacementPlugin(
/zone\.js(\\|\/)dist(\\|\/)long-stack-trace-zone/,
helpers.root('config/empty.js')
),
// AoT
// new NormalModuleReplacementPlugin(
// /@angular(\\|\/)upgrade/,
// helpers.root('config/empty.js')
// ),
// new NormalModuleReplacementPlugin(
// /@angular(\\|\/)compiler/,
// helpers.root('config/empty.js')
// ),
// new NormalModuleReplacementPlugin(
// /@angular(\\|\/)platform-browser-dynamic/,
// helpers.root('config/empty.js')
// ),
// new NormalModuleReplacementPlugin(
// /dom(\\|\/)debug(\\|\/)ng_probe/,
// helpers.root('config/empty.js')
// ),
// new NormalModuleReplacementPlugin(
// /dom(\\|\/)debug(\\|\/)by/,
// helpers.root('config/empty.js')
// ),
// new NormalModuleReplacementPlugin(
// /src(\\|\/)debug(\\|\/)debug_node/,
// helpers.root('config/empty.js')
// ),
// new NormalModuleReplacementPlugin(
// /src(\\|\/)debug(\\|\/)debug_renderer/,
// helpers.root('config/empty.js')
// ),
/**
* Plugin: CompressionPlugin
* Description: Prepares compressed versions of assets to serve
* them with Content-Encoding
*
* See: https://github.com/webpack/compression-webpack-plugin
*/
// install compression-webpack-plugin
// new CompressionPlugin({
// regExp: /\.css$|\.html$|\.js$|\.map$/,
// threshold: 2 * 1024
// })
/**
* Plugin LoaderOptionsPlugin (experimental)
*
* See: https://gist.github.com/sokra/27b24881210b56bbaff7
*/
new LoaderOptionsPlugin({
minimize: true,
debug: false,
options: {
/**
* Html loader advanced options
*
* See: https://github.com/webpack/html-loader#advanced-options
*/
// TODO: Need to workaround Angular 2's html syntax => #id [bind] (event) *ngFor
htmlLoader: {
minimize: true,
removeAttributeQuotes: false,
caseSensitive: true,
customAttrSurround: [
[/#/, /(?:)/],
[/\*/, /(?:)/],
[/\[?\(?/, /(?:)/]
],
customAttrAssign: [/\)?\]?=/]
},
}
}),
/**
* Plugin: BundleAnalyzerPlugin
* Description: Webpack plugin and CLI utility that represents
* bundle content as convenient interactive zoomable treemap
*
* `npm run build:prod -- --env.analyze` to use
*
* See: https://github.com/th0r/webpack-bundle-analyzer
*/
],
/*
* Include polyfills or mocks for various node stuff
* Description: Node configuration
*
* See: https://webpack.github.io/docs/configuration.html#node
*/
node: {
global: true,
crypto: 'empty',
process: false,
module: false,
clearImmediate: false,
setImmediate: false
}
});
}