一、 什么是webpack

概念 | webpack 中文网

1、官方解释

本质上讲, webpack 是一个现代 JavaScript 应用程序的静态模块打包器。(模块和打包)
image.png

2、前端模块化

  • 前端模块化的一些方案: AMD、 CMD、 CommonJS、 ES6
    • 浏览器不能识别它们, 但是webpack 可以做它们的底层支撑,方可进行模块化开发
  • ES6 之前, 要想进行模块化开发, 就必须借助于其他的工具, 让我们进行模块化开发
  • 并且通过模块化开发完成了项目后, 还需要处理模块化间的各种依赖, 并且将其进行整合打包
  • 此时出现 webpack, 其中一个核心就是让我们可能进行模块化开发, 并且会帮助我们处理模块间的依赖关系。
  • 而不仅仅是JavaScript文件,我们的css、图片、json 文件等等在webpack 中都可以被当作模块来使用

3、打包如何理解

  • webpack 可以帮助我们进行模块化, 并且处理模块间的各种复杂关系后, 打包的概念就很好理解了
  • 就是将 webpack 中的各种资源模块进行打包合并成一个或多个包(bundle)
  • 并且在打包的过程中, 还可以对资源进行处理, 比如压缩图片, 将scss 转成 css, 将ES6 语法转成ES5 语法, 将TypeScript 转成 JavaScript 等等操作
  • 打包工具还有 grunt/gulp
  • webpack 和 grunt/gulp 的对比
    • grunt/gulp 的核心是Task
      • 可以配置一系列的task, 并且定义 task 要处理的事务(例如 ES6、ts转化、图片压缩、scss转成css)
      • 之后让grunt/gulp 来依次执行这些task, 而且让整个流程自动化
    • 看一个gulp 的 task
      • 下面的task 就是将src 下面的所有js 文件转成 ES5 的语法
      • 并且最终输出到dist 文件夹中
      • image.png
    • 什么时候使用grunt/gulp?
      • 工程模块依赖非常简单, 甚至没有用到模块化的概念
      • 只需要进行简单的合并、压缩, 就使用grunt/gulp 即可
      • 如果整个项目使用了模块化管理, 而且相互依赖非常强, 我们就可以使用webpack
    • grunt/gulp 和 webpack 有什么不同
      • grunt/gulp 更加强调的是前端流程的自动化, 模块化不是它的核心
      • webpack 更加强调模块化开发管理, 而文件压缩合并、预处理等功能, 是她附带的功能

二、webpack 安装

webpack 为了正常运行必须依赖node 环境, 而node 环境为了可以正常执行,必须使用 npm 工具管理 node中各种依赖包

  • 因此 安装webpack 首先要安装Node.js, Node.js 自带了软件包管理工具 npm
  • 全局安装 webpack (npm install webpack@3.6.0 -g)
  • 局部安装 webpack (npm install webpack@3.6.0 —save-dev) —save-dev 是开发时依赖,项目打包后不再需要继续使用

    三、webpack 的配置

    1、文件和文件夹解析

  • dist文件夹: 用于存放打包之后的文件

  • src 文件夹: 用于存放我们写的源文件
    • main.js 项目的入口文件
    • mathUtils.js 定义了一些数学工具函数, 可以在其他地方引用, 并且使用
    • index.html 浏览器打开展示的首页html(在这里引用的是 src 内最终打包的文件 即 dist 文件夹的内容
    • package.json 通过npm init 生成的, npm 包管理文件

(CommonJS模块化规范, CommonJS 是模块化的标准, nodejs 就是 CommonJS 模块化的实现)

2、命令

webpack ./src/main.js ./dist/bundle.js (将 main.js 文件打包成 bundle.js 文件)

说明: 也可以使用 ES6 的模块化规范

  1. // 使用commonjs 的模块化规范
  2. const { add, mul } = require('./mathUtils.js')
  3. console.log(add(20, 30));
  4. console.log(mul(20, 30));
  5. // 使用 ES6 的模块化规范
  6. import { name, age, height } from './info'
  7. console.log(name);
  8. console.log(age);
  9. console.log(height);

3、创建 webpack.config.js 文件简化打包命令

(将打包命令映射为打包入口和出口

  1. const path = require('path')
  2. module.exports = {
  3. entry: './src/main.js',
  4. output: {
  5. path: path.resolve(__dirname, 'dist'),
  6. filename: 'bundle.js'
  7. }
  8. }
  • entry: 为打包的入口
  • output: 为打包的出口
    • output 中的path 我们需要动态获取
    • 因为我们可以使用Node.js 语法导入一个模块这个模块path [ const path = require(”path”)] 引号内的文件是需要在node 包里找到
    • 通过npm init 命令(初始化)使用node.js
    • 之后生成 package.json 文件(该文件描述当前项目的信息)
      • license: “ISC” 为开源项目

说明: 如果想使用node, 必须依赖于 package.json 文件

  1. {
  2. "name": "meetwebpack",
  3. "version": "1.0.0",
  4. "description": "",
  5. "main": "index.js",
  6. "scripts": {
  7. "test": "echo \'Error: no test specified\' && exit 1"
  8. },
  9. "author": "",
  10. "license": "ISC"
  11. }

运行 npm install webpack@3.6.0 —save-dev 之后,增加了如下依赖

  1. {
  2. "name": "meetwebpack",
  3. "version": "1.0.0",
  4. "description": "",
  5. "main": "index.js",
  6. "scripts": {
  7. "test": "echo \'Error: no test specified\' && exit 1",
  8. "build": "webpack"
  9. },
  10. "author": "",
  11. "license": "ISC",
  12. "devDependencies": {
  13. "webpack": "^3.6.0"
  14. }
  15. }

4、将webpack 命令映射 npm run

除了将 webpack 映射入口、出口之外, 还可以将webpack 命令映射为 npm run 一些操作(需要在 package.json 内”script” 脚本标签中修改)

四、loader 的使用

1、什么是loader

  • loader 是webpack 中一个非常核心的概念

webpack 用来做什么?

  • 主要用webpack 处理js代码, 并且 webpack 会自动处理 js 之前相关的依赖
  • 但, 在开发中不仅要处理js代码, 还需要加载css、图片,一些高级的如将 ES6 转成ES5代码将 scss、less 转成 css 将jsx、.vue 文件转成js 文件
  • 对于webpack 本身的能力来说,这些转化是不支持的
  • 此时可以交给 webpack 扩展 对应的 loader 来处理

    2、loader 使用示例

    Loaders | webpack 中文文档

    示例1: css 文件处理

  • 通过 npm 安装需要使用的loader

    • npm install —save-dev css-loader
    • npm install —save-dev style-loader
  • 在 webpack.config.js 中的modules 关键字下进行配置

    • css-loader 只负责加载 css 文件, 并不负责将css 具体样式嵌入到文档中
    • style-loader 负责将样式添加到DOM 中
    • 使用多个loader时, 从右向左读取
      1. {
      2. ...
      3. module: [
      4. rules: [
      5. {
      6. test: /\.css$/,
      7. // css-loader 只负责将css 文件进行加载
      8. // style-loader 负责将样式添加到DOM 中
      9. // 使用多个 loader 时,从右向左
      10. use: ['style-loader', 'css-loader']
      11. }
      12. ]
      13. ]
      14. }

      示例2: less 文件处理

  • 安装对应的loader

    • npm install —save-dev less-loader less(安装less 是 对less 文件进行编译)
  • 修改对应的配置文件, webpack.config.js 文件中的rules 数组中新增一个对象处理.less 文件
    • image.png
      1. {
      2. test:/\.less$/,
      3. use: [
      4. { loader: "style-loader" // creates style nodes from JS strings },
      5. { loader: "css-loader" // translates CSS into CommonJS },
      6. { loader: "less-loader" // compiles less to css }
      7. ]
      8. }

      示例3: 图片文件处理

      npm install —save-dev file-loader

  1. {
  2. test: /\.(png|jpg|gif|jpeg)$/,
  3. use: [
  4. {
  5. loader: 'url-loader',
  6. options: {
  7. // 当加载的图片,小于limit 时, 会将图片编译成 base64 字符串形式
  8. // 当加载的图片,大于limit 时, 需要使用file-loader 模块进行加载
  9. limit: 8196
  10. }
  11. }
  12. ]
  13. }

打包后image.png会发现dist文件夹下多了一个图片文件
说明

  • webpack 会自动帮我们生成一个非常长的名字
    • 这是一个 32位 hash值, 目的是防止名字重复
    • 但是实际开发中, 可能对打包的图片名字有一定的要求
  • 可以在options 中添加如下选项
    • img: 文件要打包到的文件夹
    • name: 获取图片原来的名字,放在该位置
    • hash8: 为了防止图片名字冲突, 依然使用hash, 但只保留8位
    • ext: 使用图片原来的扩展名
      1. {
      2. test: /\.(png|jpg|gif|jpeg)$/,
      3. use: [
      4. {
      5. loader: 'url-loader',
      6. options: {
      7. // 当加载的图片,小于limit 时, 会将图片编译成 base64 字符串形式
      8. // 当加载的图片,大于limit 时, 需要使用file-loader 模块进行加载
      9. limit: 8196
      10. name: 'img/[name].[hash:8].[ext]'
      11. }
      12. }
      13. ]
      14. }
      另外, 配置图片修改图片使用的路径可以在 output 下的 publicPath 中配置

      示例4: ES6转ES5的babel

      npm install —save-dev babel-loader@7 babel-preset-es2015

配置webpack.config.js 文件

  1. {
  2. test: /\.m?js$/,
  3. exclude: /(node_modules|bower_components)/,
  4. use: {
  5. loader: 'babel-loader',
  6. option: {
  7. presets: ['es2015']
  8. }
  9. }
  10. }

重新打包后,会发现 bundle.js 文件内容变成了es5 的语法

五、plugin 的使用

HtmlWebpackPlugin | webpack 中文文档

1、认识plugin

  • plugin 是什么?
    • plugin 是插件的意思, 通常是用于对某个现有的架构进行扩展
    • webpack 中的插件, 就是对webpack现有功能的各种扩展, 比如打包优化、文件压缩等
  • loader 和 plugin区别
    • loader 主要用于转化某些类型的模块, 他是一个转化器
    • plugin 是插件, 他是对webpack本身的扩展, 是一个扩展器
  • plugin 的使用过程
    • 通过npm 安装需要使用plugins (某些webpack已经内置的插件不需要安装)
    • 在 webpack.config.js 中的plugins中配置插件

2、webpack 添加版权信息 Plugin 的使用

使用插件, 为打包的文件添加版权声明, 该插件名字叫 BannerPlugin, 属于 webpack 自带的插件

  1. const path = require('path')
  2. const webpack = require('webpack')
  3. module.exports = {
  4. ...
  5. plugins: [
  6. new webpack.BannerPlugin('最终版权归coderwhy所有')
  7. ]
  8. }

重新打包,查看bundle.js 文件的头部,有如下信息
image.png

3、打包html的plugin

image.png

4、js压缩的plugin

image.png