webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。
需要先理解四个核心概念:

  • 入口(entry)
  • 输出(output)
  • loader
  • 插件(plugins)

入口(entry)

入口指 webpack 构建其内部依赖图开始的模块。进入入口后,webpack 会找出有哪些模块和库是入口起点(直接和间接)依赖的。
在 webpack 配置中有多种方式定义 entry 属性。
用法:

  1. const config = {
    entry: {
    app: './src/app.js',
    vendors: './src/vendors.js'
    }
    };

单个入口可简写成如下:

  1. const config = {
    entry: './path/to/my/entry/file.js'
    };

以下是两种实际用例:
1.分离应用程序和第三方库入口,vue-cli中是这样做的:

  1. const config = {
    entry: {
    app: './src/app.js',
    vendors: './src/vendors.js'
    }
    };

webpack 从 app.js 和 vendors.js 开始创建依赖图。这些依赖图是彼此完全分离、互相独立的。这种方式比较常见于,只有一个入口起点(不包括 vendor)的单页应用程序(single page application)中。

2.多页面应用程序

  1. const config = {
    entry: {
    pageOne: './src/pageOne/index.js',
    pageTwo: './src/pageTwo/index.js',
    pageThree: './src/pageThree/index.js'
    }
    };

在多页应用中,页面跳转时服务器将为你获取一个新的 HTML 文档。页面重新加载新文档,并且资源被重新下载。由于入口起点增多,多页应用能够复用入口起点之间的大量代码/模块.

输出(Output)

该属性设置 webpack 在输出它所创建的 bundles的路径以及命名。
注意: 即使可以存在多个入口起点,但只指定一个输出配置。

用法:
在 webpack 中配置 output 属性的最低要求是,将它的值设置为一个对象,包括以下两点:

filename 用于输出文件的文件名。
目标输出目录 path 的绝对路径。

  1. const config = {
    output: {
    filename: 'bundle.js',
    path: '/home/proj/public/assets'
    }
    };

module.exports = config;
此配置将一个单独的 bundle.js 文件输出到 /home/proj/public/assets 目录中。

多个入口时:
如果配置创建了多个单独的 "chunk"(例如,使用多个入口起点或使用像 CommonsChunkPlugin 这样的插件),则应该使用占位符(substitutions)来确保每个文件具有唯一的名称。

  1. {
    entry: {
    app: './src/app.js',
    search: './src/search.js'
    },
    output: {
    filename: '[name].js',
    path: __dirname + '/dist'
    }
    }

复杂示例:
以下是使用 CDN 和资源 hash 的复杂示例

  1. output: {
    path: "/home/proj/cdn/assets/[hash]",
    publicPath: "http://cdn.example.com/assets/[hash]/"
    }

在编译时不知道最终输出文件的 publicPath 的情况下,publicPath 可以留空,并且在入口起点文件运行时动态设置。如果你在编译时不知道 publicPath,你可以先忽略它,并且在入口起点设置 __webpack_public_path__。

  1. __webpack_public_path__ = myRuntimePublicPath

// 剩余的应用程序入口

loader

用于对模块的源代码进行转换。loader 可以使你在 import 或"加载"模块时预处理文件。因此,loader 类似于其他构建工具中“任务(task)”,并提供了处理前端构建步骤的强大方法。loader 可以将文件从不同的语言(如 TypeScript)转换为 JavaScript,或将内联图像转换为 data URL。loader 甚至允许你直接在 JavaScript 模块中 import CSS文件!

示例:
使用loader加载 CSS 文件 和 将 TypeScript 转为 JavaScript。
首先安装对应的loader

  1. npm install --save-dev css-loader
  2. npm install --save-dev ts-loader

然后指示 webpack 对每个 .css 使用 css-loader,以及对所有 .ts 文件使用 ts-loader:

  1. module.exports = {
    module: {
    rules: [
    { test: /\.css$/, use: 'css-loader' },
    { test: /\.ts$/, use: 'ts-loader' }
    ]
    }
    };

以上配置,对一个 module 对象定义了 rules 属性,里面包含两个必须属性:test 和 use。
test 属性,用于标识出应该被对应的 loader 进行转换的某个或某些文件。
use 属性,表示进行转换时,应该使用哪个 loader。
上面的配置代表, 当webpack编译器解析时, 遇到 require()/import 语句有'.css'路径时,在打包之前先用 css-loader 转换一下;遇到 require()/import 语句有'.ts'路径时,在打包之前先用 ts-loader 转换一下

使用Loader的三种方式:

1.配置: 在 webpack.config.js 文件中指定 loader。

module.rules 允许你在 webpack 配置中指定多个 loader。 这是展示 loader 的一种简明方式,并且有助于使代码变得简洁。同时让你对各个 loader 有个全局概览:

  1. module: {
  2. rules: [
  3. {
  4. test: /\.css$/,
  5. use: [
  6. { loader: 'style-loader' },
  7. {
  8. loader: 'css-loader',
  9. options: {
  10. modules: true
  11. }
  12. }
  13. ]
  14. }
  15. ]
  16. }

2.内联: 在 import 语句或任何等效于 "import" 的方式中指定 loader。

使用 ! 将资源中的 loader 分开。分开的每个部分都相对于当前目录解析。

  1. import Styles from 'style-loader!css-loader?modules!./styles.css';

通过前置所有规则及使用 !,可以对应覆盖到配置中的任意 loader。选项可以传递查询参数,例如 ?key=value&foo=bar,或者一个 JSON 对象,例如 ?{"key":"value","foo":"bar"}。

3.通过 CLI 使用 loader:

  1. webpack --module-bind jade-loader --module-bind 'css=style-loader!css-loader'

loader 通过(loader)预处理函数,为 JavaScript 生态系统提供了更多能力。 用户现在可以更加灵活地引入细粒度逻辑,例如压缩、打包、语言翻译等loader 遵循标准的模块解析。多数情况下,loader 将从模块路径(通常将模块路径认为是 npm install, node_modules)解析。loader 模块需要导出为一个函数,并且使用 Node.js 兼容的 JavaScript 编写。通常使用 npm 进行管理,但是也可以将自定义 loader 作为应用程序中的文件。按照约定,loader 通常被命名为 xxx-loader(例如 json-loader)。

用法:
由于插件可以携带参数/选项,你必须在 webpack 配置中,向 plugins 属性传入 new 实例。
根据你的 webpack 用法,这里有多种方式使用插件。

  1. const HtmlWebpackPlugin = require('html-webpack-plugin'); //通过 npm 安装
  2. const webpack = require('webpack'); //访问内置的插件
  3. const path = require('path');
  4.  
  5. const config = {
  6. entry: './path/to/my/entry/file.js',
  7. output: {
  8. filename: 'my-first-webpack.bundle.js',
  9. path: path.resolve(__dirname, 'dist')
  10. },
  11. module: {
  12. loaders: [
  13. {
  14. test: /\.(js|jsx)$/,
  15. use: 'babel-loader'
  16. }
  17. ]
  18. },
  19. plugins: [
  20. new webpack.optimize.UglifyJsPlugin(),
  21. new HtmlWebpackPlugin({template: './src/index.html'})
  22. ]
  23. };
  24.  
  25. module.exports = config;

插件(plugins)

loader 被用于转换某些类型的模块,而插件的使用范围包括,从打包优化和压缩,一直到重新定义环境中的变量。可以用来处理各种任务.
使用某个插件,只需要require(),然后添加到 plugins 数组中.多数插件可以通过选项(option)自定义,也可以在一个配置文件中因为不同目的而多次使用同一个插件,这时需要通过使用 new 操作符来创建它的一个实例。

示例:

  1. const HtmlWebpackPlugin = require('html-webpack-plugin'); // 通过 npm 安装
  2. const webpack = require('webpack'); // 用于访问内置插件
  3. const path = require('path');
  4.  
  5. const config = {
  6. entry: './src/main.js',
  7. output: {
  8. path: path.resolve(__dirname, 'dist'), //生成文件(emit)的路径
  9. filename: 'yq-webpack.bundle.js' // webpack bundle 的名称
  10. },
  11. module: {
  12. rules: [
  13. {test: /\.txt$/, use: 'raw-loader'}
  14. ]
  15. },
  16. plugins: [
  17. new webpack.optimize.UglifyJsPlugin(),
  18. new HtmlWebpackPlugin({template: './src/index.html'})
  19. ]
  20. };
  21.  
  22. module.exports = config;

模块

  在模块化编程中,开发者将程序分解成离散功能块(discrete chunks of functionality),并称之为_模块_。

每个模块具有比完整程序更小的接触面,使得校验、调试、测试轻而易举。 精心编写的_模块_提供了可靠的抽象和封装界限,使得应用程序中每个模块都具有条理清楚的设计和明确的目的。
对比 Node.js 模块,webpack _模块_能够以各种方式表达它们的依赖关系

  • ES2015 import 语句
  • CommonJS require() 语句
  • AMD define 和 require 语句
  • css/sass/less 文件中的 @import 语句。
  • 样式(url(...))或 HTML 文件(<img src=...>)中的图片链接(image url)

resolver 是一个库(library),用于帮助找到模块的绝对路径。一个模块可以作为另一个模块的依赖模块,然后被后者引用,如下:

  1. import foo from 'path/to/module'
  2. // 或者
  3. require('path/to/module')

所依赖的模块可以是来自应用程序代码或第三方的库(library)。resolver 帮助 webpack 找到 bundle 中需要引入的模块代码,这些代码在包含在每个 require/import 语句中。 当打包模块时,webpack 使用 enhanced-resolve 来解析文件路径

webpack 中的解析规则

webpack 能够解析三种文件路径:
绝对路径:

  1. import "/home/me/file";
  2.  
  3. import "C:\\Users\\me\\file";

相对路径

  1. import "/home/me/file";
  2.  
  3. import "C:\\Users\\me\\file";

在这种情况下,使用 import 或 require 的资源文件(resource file)所在的目录被认为是上下文目录(context directory)。在 import/require 中给定的相对路径,会添加此上下文路径(context path),以产生模块的绝对路径(absolute path)。

模块路径

  1. import "module";
  2.  
  3. import "module/lib/file";

模块将在 resolve.modules 中指定的所有目录内搜索。

  1. 一旦根据上述规则解析路径后,解析器(resolver)将检查路径是否指向文件或目录。如果路径指向一个文件:
  2. 如果路径具有文件扩展名,则被直接将文件打包。
  3. 否则,将使用 [resolve.extensions] 选项作为文件扩展名来解析,此选项告诉解析器在解析中能够接受哪些扩展名(例如 .js, .jsx)。

如果路径指向一个文件夹,则采取以下步骤找到具有正确扩展名的正确文件:

  1. 如果文件夹中包含 package.json 文件,则按照顺序查找 resolve.mainFields 配置选项中指定的字段。并且 package.json 中的第一个这样的字段确定文件路径。
  2. 如果 package.json 文件不存在或者 package.json 文件中的 main 字段没有返回一个有效路径,则按照顺序查找 resolve.mainFiles 配置选项中指定的文件名,看是否能在 import/require 目录下匹配到一个存在的文件名。
  3. 文件扩展名通过 resolve.extensions 选项采用类似的方法进行解析。
  4. webpack 根据构建目标(build target)为这些选项提供了合理的默认配置。

通过核心概念了解webpack工作机制的更多相关文章

  1. Elasticsearch学习笔记(六)核心概念和分片shard机制

    一.核心概念 1.近实时(Near Realtime NRT) (1)从写入数据到数据可以被搜索到有一个小延迟(大概1秒): (2)基于es执行搜索和分析可以达到秒级 2.集群(Cluster) 一个 ...

  2. Hadoop MapReduce 一文详解MapReduce及工作机制

    @ 目录 前言-MR概述 1.Hadoop MapReduce设计思想及优缺点 设计思想 优点: 缺点: 2. Hadoop MapReduce核心思想 3.MapReduce工作机制 剖析MapRe ...

  3. Elasticsearch之重要核心概念(cluster(集群)、shards(分配)、replicas(索引副本)、recovery(据恢复或叫数据重新分布)、gateway(es索引的持久化存储方式)、discovery.zen(es的自动发现节点机制机制)、Transport(内部节点或集群与客户端的交互方式)、settings(修改索引库默认配置)和mappings)

    Elasticsearch之重要核心概念如下: 1.cluster 代表一个集群,集群中有多个节点,其中有一个为主节点,这个主节点是可以通过选举产生的,主从节点是对于集群内部来说的.es的一个概念就是 ...

  4. webpack安装与核心概念

    安装webpack webpack核心概念:入口.输出.加载器.插件.模块.模式 一.安装webpack 1.安装webpack之前需要安装nodejs环境,在使用nodejs环境自带的包管理工具np ...

  5. WebGPU 导入[2] - 核心概念与重要机制解读

    目录 1. 核心概念 ① 适配器和设备 ② 缓冲.纹理.采样器 ③ 绑定组 ④ 着色器与管线 ⑤ 编码器与队列 2. 重要机制 ① 缓冲映射机制 ② 时间线 1. 核心概念 这部分不会详细展开,以后写 ...

  6. webpack的四个核心概念介绍

    前言 webpack 是一个当下最流行的前端资源的模块打包器.当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后 ...

  7. webpack核心概念

    一.webpack四个核心概念 1.入口[Entry] webpack将创建所有应用程序 依赖关系图表.图表的起点被称之为 入口起点.入口起点告诉webpack从哪里开始,并遵循着依赖关系图表知道打包 ...

  8. RabbitMQ如何工作和RabbitMQ核心概念

    RabbitMQ是一个开源的消息代理软件.它接受来自生产者的消息并将其传递给消费者.它就像一个中间人,可以用来减少Web应用程序服务器的负载和交付时间. RabbitMQ如何工作 让我们简要介绍一下R ...

  9. hibernate学习系列-----(2)hibernate核心接口和工作机制

    在上一篇文章hibernate学习系列-----(1)开发环境搭建中,大致总结了hibernate的开发环境的搭建步骤,今天,我们继续了解有关hibernate的知识,先说说这篇文章的主要内容吧: C ...

随机推荐

  1. Hibernate 的原生 SQL 查询

    Hibernate除了支持HQL查询外,还支持原生SQL查询.         对原生SQL查询执行的控制是通过SQLQuery接口进行的,通过执行Session.createSQLQuery()获取 ...

  2. MySQL 查询最近几天的记录 最近7天的记录 本周内的记录

    本周内:select * from wap_content where week(created_at) = week(now) 查询一天:select * from table where to_d ...

  3. Linuxc - 多c文件程序编译执行

    多文件使用,一起编译 定义max.h int max(int a,int b); 定义max.c #include "max.h" int max(int a,int b) { i ...

  4. 解决svn--Unable to connect to a repository at URL ‘https://xxxxxx’ 问题

    在checkout项目时,出现如下错误: Error  Unable to connect to a repository at URL 'https://XXXX' Error  Access to ...

  5. 实现iota函数

    void Reverse(char *s) { char temp; char *p = s; char *q = s; while (*p != '\0') { p ++; } q --; whil ...

  6. TOMCAT原理详解及请求过程

    Tomcat: Tomcat是一个JSP/Servlet容器.其作为Servlet容器,有三种工作模式:独立的Servlet容器.进程内的Servlet容器和进程外的Servlet容器. Tomcat ...

  7. XML系列之--Linq操作带属性的XML(四)

    关于XML,之前解析过电文收发方面的,就是所谓的带表头.前缀(命名空间)SOAP格式.这次需求是解析一个xml的模板(xls内容),然后填充数据,最后保存.需要时可转换xls.pdf等文件.关于这种带 ...

  8. docker之NGINX镜像构建

    Nginx是一个高性能的Web和反向代理服务器,它具有很多非常优越的特性:1.作为Web服务器.2.作为负载均衡服务器.3.作为邮件代理服务器.4.安装及配置简单.接下来我们介绍在docker构建ng ...

  9. 知识点干货—多线程同步【6】之synchronized

    "明日复明日,明日何其多. 我生待明日,万事成蹉跎. 世人若被明日累,春去秋来老将至. 朝看水东流,暮看日西坠. 百年明日能几何?请君听我明日歌. 明日复明日,明日何其多! 日日待明日,万世 ...

  10. PHP 第3方评论系统

    这段时间,无觅 评论也下线不能使用了. 客户好几个网站使用了.无觅 评论,前面也是用的是多说还是什么,总之也是第3方评论,没想到没过多久,又停止使用了. 没办法,网站还是需要评论系统,一气之下,自己做 ...