深入学习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 ...
随机推荐
- [译]在Javascript中进行日期相关的操作
本文翻译youtube上的up主kudvenkat的javascript tutorial播放单 源地址在此: https://www.youtube.com/watch?v=PMsVM7rjupU& ...
- 简单的linux service(linux服务)编写,运行示例
1.写一个简单小程序 #include<stdio.h> #include<stdlib.h> int main(int argc,char **argv) { while(1 ...
- WSMBT Modbus & WSMBS Modbus 控件及注册机
先上注册机 点击下载 How to add the WSMBT control to the toolbox: On the Tools menu, click Choose Toolbox Item ...
- .Net Core异步async/await探索
走进.NetCore的异步编程 - 探索 async/await 前言: 这段时间开始用.netcore做公司项目,发现前辈搭的框架通篇运用了异步编程方式,也就是async/await方式,作为一个刚 ...
- centoOS下安装python3 和 pip: command not found
在更新python3的时候会自动安装pip3,但是安装完成后,pip -V发现出错:command not found,找了好久,发现在建立软连接的时候路径写错了. 总结一下安装python3和发现p ...
- 利用excel制作二维码
1 将想要通过扫描二维码访问的目标网址放入A1单位格 2 在excel 编辑区右击选择“自定义功能区” 3 然后将“开发者工具”选上 4 点击菜单栏的“开发者工具---插入--->其他控件” 5 ...
- c# 大文件分割 复制 Filestream 进度条
大文件分割复制,每次复制100M 也可以复制别的较大数值. 小于1G的小文件就直接复制得了.代码里没写 ,但是很简单 直接写进去就好了,难得是分割复制 所以没写. 好吧 我还是改了 改成小文件也可以复 ...
- Git 分支管理-git stash 和git stash pop
https://blog.csdn.net/u010697394/article/details/56484492 合并分支,冲突是难免的,在实际协作开发中我们遇到的情况错综复杂,今天就讲两个比较重要 ...
- RxJS的基础
RxJS是一个强大的Reactive编程库,提供了强大的数据流组合与控制能力,但是其学习门槛一直很高,本次分享期望从一些特别的角度解读它在业务中的使用,而不是从API角度去讲解. RxJS简介 通常, ...
- 析构函数-复制构造函数-赋值操作符重载-默认构造函数<代码解析>
通过下面primer中的一道习题,可以更深刻的了解,析构函数,复制构造函数,赋值操作符重载,默认构造函数的使用. 但是我的结果与primer习题解答里面的并不相同,可能是编译器不同的原因导致. // ...