深入学习webpack(三)
在前面两篇博客中,主要讲了webpack的使用和webpack的核心概念,他们都是非常重要的,在这篇博客中,讲主要讨论webpack配置相关问题。
参考文章:https://webpack.js.org/configuration/
对于配置文件中不懂的地方都可以在上面的文章中找到最精确的文档来查看学习。
第一部分
可能你已经注意到了几乎没有两个configuration是相同的,这是因为webpack的配置文件就是一个导出一个对象的js文件。这个对象将会基于自身的属性被处理。
因为这是nodejs中的Commonjs标准,所以我们可以这样做:
- 通过require()引入其他的文件。
- 通过require()使用npm中的一些功能。
- 使用js的控制流表达式如 ?: 操作符。
- 对于经常使用的值使用常量或者变量来表示。
另外,下面的这些事不推荐的:
- 当使用webpack CLI时,使用CLI参数。
- 导出不确定的值。
- 写了很长的配置(而不是将配置文件分割为多份不同功能的配置文件)。 比如我们使用vue-cli时就会发现webpack的配置文件有4个之多,这就是为了防止一个配置文件过大而冗杂。
下面就是一个最简单的配置文件:
var path = require('path');
module.exports = {
entry: './foo.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'foo.bundle.js'
}
};
下面也是一个配置文件,它是包含多对象的:
var path = require('path');
var webpack = require('webpack');
var webpackMerge = require('webpack-merge');
var baseConfig = {
target: 'async-node',
entry: {
entry: './entry.js'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js'
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: 'inline',
filename: 'inline.js',
minChunks: Infinity
}),
new webpack.optimize.AggressiveSplittingPlugin({
minSize: ,
maxSize:
}),
]
};
let targets = ['web', 'webworker', 'node', 'async-node', 'node-webkit', 'electron-main'].map((target) => {
let base = webpackMerge(baseConfig, {
target: target,
output: {
path: path.resolve(__dirname, 'dist/' + target),
filename: '[name].' + target + '.js'
}
});
return base;
});
module.exports = targets;
对于这个配置文件,有下面几点需要说明:
- 对于配置文件,我们有很多种组织方式来配置, 最重要的是坚持一致性并且保证你的团队都可以理解并维护他们。
- 对于多个对象,我们常用的就是webpackMerge函数,这个函数可以将多个对象merge为一个对象。
- 这里最后导出的是一个targets数组,其中的每一个元素都是合并之后的对象。
第二部分
不难发现,之前我们在写配置文件时往往会用到node的内置模块---path模块。通过传入全局变量__dirname来使用。 这样可以防止出现文件的路径错误问题,因为不同的操作系统和对于相对路径/绝对路径的支持问题。
const path = require('path');
module.exports = {
// click on the name of the option to get to the detailed documentation
// click on the items with arrows to show more examples / advanced options
entry: "./app/entry", // string | object | array
// Here the application starts executing
// and webpack starts bundling
output: {
// options related to how webpack emits results
path: path.resolve(__dirname, "dist"), // string
// the target directory for all output files
// must be an absolute path (use the Node.js path module)
filename: "bundle.js", // string
// the filename template for entry chunks
publicPath: "/assets/", // string
// the url to the output directory resolved relative to the HTML page
library: "MyLibrary", // string,
// the name of the exported library
libraryTarget: "umd", // universal module definition
// the type of the exported library
/* Advanced output configuration (click to show) */
},
module: {
// configuration regarding modules
rules: [
// rules for modules (configure loaders, parser options, etc.)
{
test: /\.jsx?$/,
include: [
path.resolve(__dirname, "app")
],
exclude: [
path.resolve(__dirname, "app/demo-files")
],
// these are matching conditions, each accepting a regular expression or string
// test and include have the same behavior, both must be matched
// exclude must not be matched (takes preferrence over test and include)
// Best practices:
// - Use RegExp only in test and for filename matching
// - Use arrays of absolute paths in include and exclude
// - Try to avoid exclude and prefer include
issuer: { test, include, exclude },
// conditions for the issuer (the origin of the import)
enforce: "pre",
enforce: "post",
// flags to apply these rules, even if they are overridden (advanced option)
loader: "babel-loader",
// the loader which should be applied, it'll be resolved relative to the context
// -loader suffix is no longer optional in webpack2 for clarity reasons
// see webpack 1 upgrade guide
options: {
presets: ["es2015"]
},
// options for the loader
},
{
test: "\.html$",
use: [
// apply multiple loaders and options
"htmllint-loader",
{
loader: "html-loader",
options: {
/* ... */
}
}
]
},
{ oneOf: [ /* rules */ ] },
// only use one of these nested rules
{ rules: [ /* rules */ ] },
// use all of these nested rules (combine with conditions to be useful)
{ resource: { and: [ /* conditions */ ] } },
// matches only if all conditions are matched
{ resource: { or: [ /* conditions */ ] } },
{ resource: [ /* conditions */ ] },
// matches if any condition is matched (default for arrays)
{ resource: { not: /* condition */ } }
// matches if the condition is not matched
],
/* Advanced module configuration (click to show) */
},
resolve: {
// options for resolving module requests
// (does not apply to resolving to loaders)
modules: [
"node_modules",
path.resolve(__dirname, "app")
],
// directories where to look for modules
extensions: [".js", ".json", ".jsx", ".css"],
// extensions that are used
alias: {
// a list of module name aliases
"module": "new-module",
// alias "module" -> "new-module" and "module/path/file" -> "new-module/path/file"
"only-module$": "new-module",
// alias "only-module" -> "new-module", but not "module/path/file" -> "new-module/path/file"
"module": path.resolve(__dirname, "app/third/module.js"),
// alias "module" -> "./app/third/module.js" and "module/file" results in error
// modules aliases are imported relative to the current context
},
/* alternative alias syntax (click to show) */
/* Advanced resolve configuration (click to show) */
},
performance: {
hints: "warning", // enum
maxAssetSize: , // int (in bytes),
maxEntrypointSize: , // int (in bytes)
assetFilter: function(assetFilename) {
// Function predicate that provides asset filenames
return assetFilename.endsWith('.css') || assetFilename.endsWith('.js');
}
},
devtool: "source-map", // enum
// enhance debugging by adding meta info for the browser devtools
// source-map most detailed at the expense of build speed.
context: __dirname, // string (absolute path!)
// the home directory for webpack
// the entry and module.rules.loader option
// is resolved relative to this directory
target: "web", // enum
// the environment in which the bundle should run
// changes chunk loading behavior and available modules
externals: ["react", /^@angular\//],
// Don't follow/bundle these modules, but request them at runtime from the environment
stats: "errors-only",
// lets you precisely control what bundle information gets displayed
devServer: {
proxy: { // proxy URLs to backend development server
'/api': 'http://localhost:3000'
},
contentBase: path.join(__dirname, 'public'), // boolean | string | array, static file location
compress: true, // enable gzip compression
historyApiFallback: true, // true for index.html upon 404, object for multiple paths
hot: true, // hot module replacement. Depends on HotModuleReplacementPlugin
https: false, // true for self-signed, object for cert authority
noInfo: true, // only errors & warns on hot reload
// ...
},
plugins: [
// ...
],
// list of additional plugins
/* Advanced configuration (click to show) */
}
在上面的配置文件中我们应该可以找到大部分遇到的问题了。
配置语言
webpack允许你使用任何语言来写配置文件。配置文件支持的语言我们可以在node-interpret中看到。也就是说,webpack在node-interpret的支持下将会根据你的选择语言来运行你的配置文件。
比如,你可以使用coffeescript,如下所示:
HtmlWebpackPlugin = require('html-webpack-plugin')
webpack = require('webpack')
path = require('path')
config =
entry: './path/to/my/entry/file.js'
output:
path: path.resolve(__dirname, 'dist')
filename: 'my-first-webpack.bundle.js'
module: rules: [ {
test: /\.(js|jsx)$/
use: 'babel-loader'
} ]
plugins: [
new (webpack.optimize.UglifyJsPlugin)
new HtmlWebpackPlugin(template: './src/index.html')
]
module.exports = config
这样的配置文件也是可以正常执行的。
配置类型
对于一个配置文件,我们除了可以导出一个配置对象,还有很多其他的方式来满足满足我们的需求。
为使用 --env 导出一个函数
最终你将会发现这样一个需求:在你的webpack.config.js中消除development和production builds之间的歧义。你至少有两个选择:
不是导出一个配置对象,而是导出一个返回的函数,这个函数可以接受环境参数作为变量。当你运行webpack时,你可以指定构建环境的关键词通过 --env, 比如使用 --env.production 或者是 --env.platform=web。 如下所示;
-module.exports = {
+module.exports = function(env) {
+ return {
plugins: [
new webpack.optimize.UglifyJsPlugin({
+ compress: env.production // compress only in production build
})
]
+ };
};
其中的+标识新添加的代码,其中的-标识不需要、删除的代码。
导出一个promise
webpack将会运行通过配置文件导出的函数并且等待一个promise被返回,当你需要异步的加载配置变量时这是非常方便的。
module.exports = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve({
entry: './app.js',
/* ... */
})
}, )
})
}
导出多个配置文件
不是导出一个配置对象或函数,你可以导出多个配置文件。 当运行webpack时,所有的配置文件都会被建立, 比如,在创建一个库时这是非常有用的
module.exports = [{
output: {
filename: './dist-amd.js',
libraryTarget: 'amd'
},
entry: './app.js',
}, {
output: {
filename: './dist-commonjs.js',
libraryTarget: 'commonjs'
},
entry: './app.js',
}]
//webpack.js.org/guides/production-build/
深入学习webpack(三)的更多相关文章
- 深入学习webpack(二)
深入学习webpack(二) 在深入学习webpack(一)中,我通过一个例子介绍了webpack的基本使用方法,下面将更为系统的学习webpack的基本概念,对于一门技术的掌握我认为系统化还是很重要 ...
- Oracle学习笔记三 SQL命令
SQL简介 SQL 支持下列类别的命令: 1.数据定义语言(DDL) 2.数据操纵语言(DML) 3.事务控制语言(TCL) 4.数据控制语言(DCL)
- 从零开始学习jQuery (三) 管理jQuery包装集
本系列文章导航 从零开始学习jQuery (三) 管理jQuery包装集 一.摘要 在使用jQuery选择器获取到jQuery包装集后, 我们需要对其进行操作. 本章首先讲解如何动态的创建元素, 接着 ...
- 前端学习 第三弹: JavaScript语言的特性与发展
前端学习 第三弹: JavaScript语言的特性与发展 javascript的缺点 1.没有命名空间,没有多文件的规范,同名函数相互覆盖 导致js的模块化很差 2.标准库很小 3.null和unde ...
- Android Animation学习(三) ApiDemos解析:XML动画文件的使用
Android Animation学习(三) ApiDemos解析:XML动画文件的使用 可以用XML文件来定义Animation. 文件必须有一个唯一的根节点: <set>, <o ...
- 三、Android学习第三天——Activity的布局初步介绍(转)
(转自:http://wenku.baidu.com/view/af39b3164431b90d6c85c72f.html) 三.Android学习第三天——Activity的布局初步介绍 今天总结下 ...
- JavaWeb学习总结(三)——Tomcat服务器学习和使用(二) 包含https 非对称秘钥 NB
JavaWeb学习总结(三)--Tomcat服务器学习和使用(二) 一.打包JavaWeb应用 在Java中,使用"jar"命令来对将JavaWeb应用打包成一个War包,jar命 ...
- MyEclipse Spring 学习总结三 SpringMVC
MyEclipse Spring 学习总结三 SpringMVC 一.SpringMVC原理 1.Springmvc 框架介绍 1)Spring 框架停工了构建Web应用程序的全功能MVC模块.Spr ...
- Quartz定时任务学习(二)web应用/Quartz定时任务学习(三)属性文件和jar
web中使用Quartz 1.首先在web.xml文件中加入 如下内容(根据自己情况设定) 在web.xml中添加QuartzInitializerServlet,Quartz为能够在web应用中使用 ...
- MyBatis学习系列三——结合Spring
目录 MyBatis学习系列一之环境搭建 MyBatis学习系列二——增删改查 MyBatis学习系列三——结合Spring MyBatis在项目中应用一般都要结合Spring,这一章主要把MyBat ...
随机推荐
- C指针的解析
这是我从网上转载的一篇关于C指针的文章,方便自己以后回顾,自己添加修改部分内容 ,不对请指正 Attention:指针是指针变量 ,数组是指针常量 第一章 指针的概念 指针是一个特殊的变量,它里面存 ...
- 回溯法和DFS leetcode Combination Sum
代码: 个人浅薄的认为DFS就是回溯法中的一种,一般想到用DFS我们脑中一般都有一颗解法树,然后去按照深度优先搜索去寻找解.而分支界限法则不算是回溯,无论其是采用队列形式的还是优先队列形式的分支界限法 ...
- [转]delphi xe6 android屏幕操持常亮
1) setting the Project Options, Uses Permissions, Wake lock = True 2) Adding Android.JNI.PowerManage ...
- NPOI读取Excel文件
public class ExcelOperator { public static List<DataTable> Read(string fileName) { List<Dat ...
- NMS---非极大值抑制
在物体检测中,NMS(Non-maximum suppression)应用十分广泛,其目的是为了消除多余的框,找到最佳的物体检测的位置.在RCNN系列算法中,会从一张图片中找出很多个候选框(可能包含物 ...
- Educational Codeforces Round 61 (Rated for Div. 2)D(二分,模拟,思维)
#include<bits/stdc++.h>using namespace std;typedef long long ll;int n,k;ll a[200007],b[200007] ...
- 数据结构5: 链表(单链表)的基本操作及C语言实现
逻辑结构上一个挨一个的数据,在实际存储时,并没有像顺序表那样也相互紧挨着.恰恰相反,数据随机分布在内存中的各个位置,这种存储结构称为线性表的链式存储. 由于分散存储,为了能够体现出数据元素之间的逻辑关 ...
- 设置SQL脚本大小敏感
1.设置SQL脚本大小写不敏感 USE [master] GO ALTER DATABASE [DatabaseName] COLLATE Chinese_PRC_CI_AI GO 2.设置大S ...
- HDU6312 Game (多校第二场1004) 简单博弈
Game Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- Android自动化----adb shell,appium,uiautomator2
1.区别 1,adb shell脚本的方式 不但可以在有电脑的情况下使用,通过数据线连接电脑然后adb shell命令,而且还可以打包成app,在手机的终端使用adb shell命令. 2,appiu ...