基础
- 模块化
CommonJS: 用于Node.js环境
// 导出
module.exports = moduleA.func;
// 导入
const moduleA = require( url );
AMD: 用于Node.js环境,浏览器。异步方式家在模块 -> requirejs
// 定义模块
define( 'module', ['dep'], function(dep) {
return exports;
} )
// 导入模块
require( ['module'], function(module) {} )
ES6模块化: 需要转化成es5运行
// 导出
export function hello(){};
export default {};
// 导入
import { A } from url;
import B from url;
一直计划说详细学一下webpack,然后由于各种因素拖到了现在。 结合《深入浅出Webpack》和官方文档。
概念: 静态模块打包器(module bundler), 将从入口开始 构建整个应用的依赖关系图,然后将所有模块打包成一个或者多个bundle。
- 入口(entry): 应用从哪个文件作为依赖图的开始。
- 出口(output): 在哪里输出根据依赖图所创建的bundles, 以及如何命名这些文件。【默认为./dist】
- 插件(plugins): loader 被用于转换某些类型的模块,而插件则可以用于执行范围更广的任务。插件的范围包括,从打包优化和压缩,一直到重新定义环境中的变量。
- 模式(mode): 可以启用响应模式下的webpack内置的优化(development, production)
- Chunk: 一个chunk由多个模块组成, 用于代码合并与分割。
- module: 处理模块的规则
- resolve:寻找模块的规则
1. Entry: 可配置 多页面应用 或者 多入口的单页应用
const config = {
entry: './path/to/my/entry/file.js' // string 类型
};
const config = {
entry: ['./path/to/my/entry/file1.js', './path/to/my/entry/file2.js'] // array 类型
// 数组里的最后一个入口文件的模块会被导出。
};
const config = {
entry: { // object 类型
pc: './pc/pc.js',
h5: './h5/h5.js',
}
};
2. Output:
const config = {
output: {
filename: "", // string 类型
chunkFilename: "", // string 需要在runtime根据chunk发送的请求去生成
path: path.resolve(__dirname, 'dist/assets'),
publicPath: "", // 静态资源的路径。 需要按照开发环境或者生产环境配置
library:"", // string 导出库的名称
libraryTarget: "", // enum 已何种方式导出库
libraryExport: "", // string, array 导出那些子模块
}
};
内置变量列表:
- id: Chunk的唯一标识, 从0开始
- name: Chunk的名称
- hash:Chunk的唯一标识的Hash值
- chunkhash: Chunk内容的Hash值
- query 模块文件名 ? 后面的字符串
注: Hash的长度是可以指定的如:[hash:8] ,默认20
其他配置项 在官方文档中有介绍或者后续的笔记中更新。
3. Module: 如何处理不同类型的模块
const config = {
module: {
noParse: /jquery/ , // 忽略部分文件的解析和处理( 被忽略的文件不该包含import, require, define)
rules: [ // 配置Loader
{
test: /\.css/, // 正则表达式的匹配规则, 也可是个array
use: [], // 数组中可以是string, object
enforce: "pre", // enum ["pre", "post"]
include: path.resolve(__dirname, 'src'),// 仅匹配src目录中的文件
exclude: path.resolve(__dirname, 'dist'),// 排除dist目录中的文件
and: [], // 必须匹配所有条件
or: [],
not: [],
}
],
parser: { // 指定解析器的开关, 精确控制哪些语法可以被解析
amd: false,
commonjs: true,
}
}
};
其中当use中,设置为对象时, 可以向其loader传入多个参数
use: [
{
loader: "", // 所使用的loader
options: {}, // 向loader传入的参数
}
]
使用oneOf,对匹配规则进行嵌套,
rules: [ // 配置Loader
{
test: /\.css/,
oneOf: [ // 可以指定嵌套规则
{
resourceQuery: /inline/, // foo.css?inline
use: 'url-loader'
},
{
resourceQuery: /external/, // foo.css?external
use: 'file-loader'
}
],
}
]
配置loader 通过一下方式完成:
- 条件匹配: 通过test,include,exclude
- 应用规则: 通过use应用loader
- 重置顺序: 默认loader的顺序是从右向左的, 使用enforce选项将loader的执行顺序改变
4. Resolve: 模块如何被解析, (webpack本身含有默认值)
const config = {
resolve: {
alias: { // 创建别名。 使引用是更方便,避免过多的相对路径
images: path.resolve(__dirname, 'src/images/')
css$: path.resolve(__dirname, 'src/assets/css') // $ 标识精准匹配
},
extensions: [".js",".json"], // 当无后缀名时,默认自动带上后缀解析
mainFiles: [], // 指定导入模块时 导入的哪部分代码
modules: ["node_modules"], // 默认只去node_modules中寻找第三方模块
enforceExtension: false, // 允许无扩展名文件的引用
unsafeCache: /\aa/, // 开启仅缓存aa模块 regex, array, boolean
plugins: [], // 额外的解析插件列表
}
}
mainFiles, 默认为["browser", "module", "main"], 默认顺序
在其他target时, 默认为["module","main"]
即 对应 所引用包的package.json中的
{
main: "build/d3.Node.js",
browser: "build/d3.js",
module: "index",
}
5. Plugins:
const config = {
plugins: [ // array
// 每项是一个插件的实例, 将参数通过构造函数传入
new CommonsChunkPlugin({ // 将所有公共代码提取到common代码块中
name: "common",
chunks: ["a","b"]
})
]
}
6. DevServer: 在开发中的行为
const config = {
devServer: {
host: "", // 默认为localhost, 设置为ip 供外部访问
port: "", // 监听的端口, 默认8080
inline: true, // false 时 责启用iframe模式, true为嵌入bundle中
allowedHosts: [], // 设置白名单
compress: true, // 启用gzip压缩
contentBase: path.join(__dirname, "public"), // 从哪提取静态文件, 默认当前执行的目录 ./
disableHostCheck: false, // 关闭host检查,使其他设备也能访问本地服务
lazy: true, // 开启惰性模式,仅在请求时编译,即不监听文件改动
filename: "", // 只在请求该文件时编译, 必须开启惰性模式
headers: {}, // 在所有想用中添加首部内容
hot: true, // 开启模块热替换,仅刷新改变的模块
clientLogLevel: "info", // enum 客户端的日志级别,默认info
https: true, // 默认使用http服务,开启https 后自动生成一份证书,也可用{}配置自己的证书,读文件
open: true, // 第一次构建后 自动打开浏览器
proxy: {
"/api": "http://localhost:3000",
"/users": {
target: "https://localhost:3000",
pathRewrite: {"^/users" : ""}, // 将路径重写 如 /users/login -> /login
secure: false, // 若代理到https服务,则需要将secure设为false
bypass: function(req, res, proxyOptions) {
if (req.headers.accept.indexOf("html") !== -1) {
console.log("Skipping proxy for browser request.");
return "/index.html";
}
}
}
},
quiet: true, // 除初始启动信息外都不会打印到控制台
}
}
proxy: [{ // 针对多个请求 进行代理
context: ["/auth", "/api"],
target: "http://localhost:3000",
}]
7. Devtool:配置source map
const config = {
devtool: "none" // 构建source-map方便调试 enum
}
具体的选项和构建速度 在官方文档中有详细的表格
8. Target:配置source map
const config = {
target: "web", // enum 默认web, 还有node,webworker, electron等
const webpack = require("webpack");
const options = {
target: (compiler) => { // function 使用非自带的target的插件
compiler.apply(
new webpack.JsonpTemplatePlugin(options.output),
new webpack.LoaderTargetPlugin("web")
);
}
};
9. Watch: 监听规则
const config = {
watch: true, // 默认false, 在devServer中默认开启
watchOptions: {
ignored: /node_modules/, // 或者使用"files/**/*.js" 这种形式
poll: 1000, // number, boolean 每秒进行轮询
aggregateTimeout: 300, // 监听到变化后 延迟300ms再执行
}
}
10. Externals不打包某些模块
const config = {
externals: {
jquery: 'jQuery' // string, array. object, function, regex
}
}
因为全局引入了一些模块或变量,然后import的时候,会使webpack将模块再打包一次,所以会出现重复的内容,使用externals排除在外。
11. Performance
const config = {
performance: {
hints: "warning", // 打开提示,在开发环境使用warning,生产error
maxEntrypointSize: 400000, // 根据入口起点的最大体积,控制 webpack 何时生成性能提示 默认值 250000 bytes
maxAssetSize: 100000, // 根据单个资源体积,控制 webpack 何时生成性能提示
assetFilter: function(assetFilename) { // 只给出 .js 文件的性能提示。
return assetFilename.endsWith('.js');
}
}
}
12. Stats
stats: "minimal", // string enum 只在发生错误或有新的编译时输出
stats: {}, // 使用对象对统计信息 进行更精确的控制
至此 ,文档中的概念,配置,Loaders, plugins 已完成概览。接下来抽空完成,实战, 优化, 原理。