前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版

webpack学习总结(二)

首页2017-01-14 17:40:43Build
Webpack

声明 本教程整理于互联网

webpack是当下最热门的前端资源模块化管理和打包工具。它可以将许多松散的模块按照依赖和规则打包成符合生产环境部署的前端资源。还可以将按需加载的模块进行代码分隔,到实际需要的时候再异步加载。通过 loader 的转换,任何形式的资源都可以视作模块,比如CommonJs模块、 AMD 模块、 ES6 模块、CSS、图片、 JSON、Coffeescript、 LESS等

# 一、模块系统的演进


  • 模块系统主要解决模块的定义、依赖和导出,先来看看已经存在的模块系统

  • <script>标签

<script src="module1.js"></script>
<script src="module2.js"></script>
<script src="libraryA.js"></script>
<script src="module3.js"></script>
@前端进阶之旅: 代码已经复制到剪贴板
  • 这是最原始的 JavaScript 文件加载方式,如果把每一个文件看做是一个模块,那么他们的接口通常是暴露在全局作用域下,也就是定义在 window 对象中,不同模块的接口调用都是一个作用域中,一些复杂的框架,会使用命名空间的概念来组织这些模块的接口,典型的例子如 YUI 库

  • 这种原始的加载方式暴露了一些显而易见的弊端

    • 全局作用域下容易造成变量冲突
    • 文件只能按照 <script> 的书写顺序进行加载
    • 开发人员必须主观解决模块和代码库的依赖关系
    • 在大型项目中各种资源难以管理,长期积累的问题导致代码库混乱不堪

# 1.1 CommonJS


  • 服务器端的 Node.js 遵循 CommonJS规范,该规范的核心思想是允许模块通过require方法来同步加载所要依赖的其他模块,然后通过 exports 或 module.exports 来导出需要暴露的接口
require("module");
require("../file.js");
exports.doStuff = function() {};
module.exports = someValue;
@前端进阶之旅: 代码已经复制到剪贴板
  • 优点:

    • 服务器端模块便于重用
    • NPM 中已经有将近20万个可以使用模块包
    • 简单并容易使用
  • 缺点:

    • 同步的模块加载方式不适合在浏览器环境中,同步意味着阻塞加载,浏览器资源是异步加载的
    • 不能非阻塞的并行加载多个模块
  • 实现

  • 服务器端的 Node.js

  • Browserify,浏览器端的 CommonJS 实现,可以使用 NPM 的模块,但是编译打包后的文件体积可能很大

  • modules-webmake,类似Browserify,还不如 Browserify 灵活

  • wreq,Browserify 的前身

# 1.2 AMD


Asynchronous Module Definition 规范其实只有一个主要接口define(id?, dependencies?,factory) ,它要在声明模块的时候指定所有的依赖 dependencies ,并且还要当做形参传到factory 中,对于依赖的模块提前执行,依赖前置

define("module", ["dep1", "dep2"], function(d1, d2) {
return someExportedValue;
});require(["module", "../file"], function(module, file) { /* ... */ });
@前端进阶之旅: 代码已经复制到剪贴板
  • 优点:

    • 适合在浏览器环境中异步加载模块
    • 可以并行加载多个模块
  • 缺点:

    • 提高了开发成本,代码的阅读和书写比较困难,模块定义方式的语义 不顺畅
    • 不符合通用的模块化思维方式,是一种妥协的实现
  • 实现:

    • RequireJS
    • curl

# 1.3 CMD


  • Common Module Definition 规范和 AMD 很相似,尽量保持简单,并与 CommonJS 和Node.js 的 Modules 规范保持了很大的兼容性
define(function(require, exports, module) {
var $ = require('jquery');
var Spinning = require('./spinning');
exports.doSomething = ...
module.exports = ...
})
@前端进阶之旅: 代码已经复制到剪贴板
  • 优点:
    • 依赖就近,延迟执行
    • 可以很容易在 Node.js 中运行
  • 缺点:
    • 依赖 SPM 打包,模块的加载逻辑偏重
  • 实现:
    • Sea.js
    • coolie

# 1.4 ES6 模块


  • EcmaScript6 标准增加了 JavaScript 语言层面的模块体系定义。ES6 模块的设计思想,是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。CommonJS 和AMD 模块,都只能在运行时确定这些东西
import "jquery";
export function doStuff() {}
module "localModule" {}
@前端进阶之旅: 代码已经复制到剪贴板
  • 优点:
    • 容易进行静态分析
    • 面向未来的 EcmaScript标准
  • 缺点:
    • 原生浏览器端还没有实现该标准
    • 全新的命令字,新版的 Node.js才支持
  • 实现:
    • Babel

# 1.5 前端模块加载


  • 前端模块要在客户端中执行,所以他们需要增量加载到浏览器中
  • 模块的加载和传输,我们首先能想到两种极端的方式,一种是每个模块文件都单独请求,另一种是把所有模块打包成一个文件然后只请求一次。显而易见,每个模块都发起单独的请求造成了请求次数过多,导致应用启动速度慢;一次请求加载所有模块导致流量浪费、初始化过程慢。这两种方式都不是好的解决方案,它们过于简单粗暴
  • 分块传输,按需进行懒加载,在实际用到某些模块的时候再增量更新,才是较为合理的模块加载方案
  • 要实现模块的按需加载,就需要一个对整个代码库中的模块进行静态分析、编译打包的过 程

# 1.6 所有资源都是模块


在上面的分析过程中,我们提到的模块仅仅是指JavaScript模块文件。然而,在前端开发过程中还涉及到样式、图片、字体、HTML 模板等等众多的资源。这些资源还会以各种方言的形式存在,比如 coffeescript、 less、 sass、众多的模板库、多语言系统(i18n)等

  • 如果他们都可以视作模块,并且都可以通过 require 的方式来加载,将带来优雅的开发体验,比如
require("./style.css");
require("./style.less");
require("./template.jade");
require("./image.png");
@前端进阶之旅: 代码已经复制到剪贴板
  • 那么如何做到让 require 能加载各种资源呢?

# 1.7 静态分析


在编译的时候,要对整个代码进行静态分析,分析出各个模块的类型和它们依赖关系,然后将不同类型的模块提交给适配的加载器来处理。比如一个用 LESS 写的样式模块,可以先用LESS 加载器将它转成一个CSS 模块,在通过 CSS 模块把他插入到页面的 <style> 标签中执行。Webpack 就是在这样的需求中应运而生

# 二、webpack基础知识


# 2.1 什么是 Webpack


  • Webpack 是一个模块打包器。它将根据模块的依赖关系进行静态分析,然后将这些模块按照指定的规则生成对应的静态资源

# 2.2 Webpack 的特点


  • 代码拆分

    • Webpack 有两种组织模块依赖的方式,同步和异步。异步依赖作为分割点,形成一个新的块。在优化了依赖树后,每一个异步区块都作为一个文件被打包
  • Loader

    • Webpack 本身只能处理原生的 JavaScript 模块,但是 loader 转换器可以将各种类型的资源转换成 JavaScript 模块。这样,任何资源都可以成为 Webpack 可以处理的模块
  • 智能解析

    • Webpack 有一个智能解析器,几乎可以处理任何第三方库,无论它们的模块形式是CommonJS、 AMD 还是普通的 JS 文件。甚至在加载依赖的时候,允许使用动态表达式require("./templates/" + name + ".jade")
  • 插件系统

    • Webpack 还有一个功能丰富的插件系统。大多数内容功能都是基于这个插件系统运行的,还可以开发和使用开源的 Webpack 插件,来满足各式各样的需求
  • 快速运行

    • Webpack 使用异步 I/O 和多级缓存提高运行效率,这使得 Webpack 能够以令人难以置信的速度快速增量编译

# 2.3 总览


  • 他的目的就是把有依赖关系的各种文件打包成一系列的静 态资源
  • webpack简单点来说就就是一个配置文件,所有的魔力都是在这一个文件中发生的。 这个配置文件主要分 为三大块
    • entry 入口文件 让webpack用哪个文件作为项目的入口
    • output 出口 让webpack把处理完成的文件放在哪里
    • module 模块 要用什么不同的模块来处理各种类型的文件

# 2.4 安装


  • 先装好node和npm,因为webpack是一个基于node的项目。然后
npm install -g webpack
@前端进阶之旅: 代码已经复制到剪贴板
  • 此时 Webpack 已经安装到了全局环境下,可以通过命令行 webpack -h 试试
  • 通常我们会将 Webpack 安装到项目的依赖中,这样就可以使用项目本地版本的 Webpack
# 进入项目目录
# 确定已经有 package.json,没有就通过 npm init 创建
# 安装 webpack 依赖
$ npm install webpack --save-dev
@前端进阶之旅: 代码已经复制到剪贴板

Webpack 目前有两个主版本,一个是在 master 主干的稳定版,一个是在 webpack-2 分支的测试版,测试版拥有一些实验性功能并且和稳定版不兼容,在正式项目中应该使用稳定版

# 查看 webpack 版本信息
$ npm info webpack
# 安装指定版本的 webpack
$ npm install webpack@1.12.x --save-dev
@前端进阶之旅: 代码已经复制到剪贴板
  • 如果需要使用 Webpack 开发工具,要单独安装
$ npm install webpack-dev-server --save-dev
@前端进阶之旅: 代码已经复制到剪贴板

# 2.5 建立一个项目


mkdir webpack
cd webpack
npm init
@前端进阶之旅: 代码已经复制到剪贴板
  • 如果你使用git管理你的这个项目的话,建议你新建一个.gitignore文件,不要让git提交一些node依赖的模 块
  • 创建一个静态页面 index.html 和一个 JS 入口文件 entry.js:
<!-- index.html -->
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<script src="bundle.js"></script>
</body>
</html>
@前端进阶之旅: 代码已经复制到剪贴板
// entry.js
document.write('It works.')
@前端进阶之旅: 代码已经复制到剪贴板
  • 然后编译 entry.js 并打包到 bundle.js:
$ webpack entry.js bundle.js
@前端进阶之旅: 代码已经复制到剪贴板
  • 打包过程会显示日志:
fe
  • 一、模块系统的演进
    • 1.1 CommonJS
    • 1.2 AMD
    • 1.3 CMD
    • 1.4 ES6 模块
    • 1.5 前端模块加载
    • 1.6 所有资源都是模块
    • 1.7 静态分析
  • 二、webpack基础知识
    • 2.1 什么是 Webpack
    • 2.2 Webpack 的特点
    • 2.3 总览
    • 2.4 安装
    • 2.5 建立一个项目
  • 三、Loader
    • 3.1 loader 有哪些特性
  • 四、配置webpack
    • 4.1 配置webpack-dev-server
    • 4.2 添加CSS样式
    • 4.3 处理图片和其他静态文件
    • 4.4 添加第三方库
    • 4.5 添加ES6的支持
  • 五、插件
  • 六、开发环境
  • 七、故障处理
  • 八、开发和部署技巧
    • 8.1 启用source-map
    • 8.2 使用preLoaders和postLoaders
    • 8.3 部署上线

← 基于gulp的工作流配置原生JS与jQuery操作DOM对比 →