Webpack 基础篇

1,116 阅读8分钟

前言


  最近一直在学习Webpack,以前也断断续续的学习过Webpack相关知识,但总是零零散散的,于是想着在这里进行一个学习总结,那么我们开始吧~


什么是Webpack

我们先看看官网是怎么定义的:

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

  简单来说Webpack是一个现代的JavaScript模块打包工具,它能够解决各模块之间的依赖,并且把各个模块按照特定的规则和顺序组织在一起,最终合并成一个或者多个js文件。这个过程就是模块打包。

  我们可以把Webpack理解成一个模块加工厂。它接受源代码,并对其进行加工等一系列操作,最终产出资源文件,等待出厂送往用户。

使用Webpack的意义

  在web开发中,我们通常用的无非是HTML, CSS, JS等静态资源,那我们为什么不把工程中的源文件直接发布到服务器而是要交给webpack进行处理呢?其实开发一个简单的web应用这样确实没问题(依稀还记得以前某某大佬直接用记事本进行开发的故事~)因为以前需求很简单,但是当应用规模大了,就必须要借助一定的工具了,所谓工欲善其事,必先利其器就是这个道理了。

那使用Webpack的意义是什么呢?我理解的是它能够让我们使用模块化的方式进行应用程序的开发

什么是模块

其实我们每时每刻都在和模块打交道,一个npm包,一个js文件我们都能够称之为模块。我们可以把模块理解为医院中的不同部门,每一个都有其特定的功能,而各个部门协同工作,才能使医院正常运转。

js模块的发展

其实在js设计之初是没有模块这个概念的,如果工程中有多个js文件,我们只能通过javaSript标签将它们一个一个插入到页面中。而随着业务的不断发展,这种需要手动维护js加载顺序的方式越来越困难了,并且每个script标签的顶层作用域就是全局作用域,如果没有任何处理直接在代码中进行变量或者函数声明,就会造成全局作用域的污染。而模块化解决了这些问题。

模块化规范

(1)common.js

  • 把每个文件都单独区分成一个模块,与最初使用script形式引入文件都方式不同,script都顶层作用域是全局作用域,在变量声明都时候可能会污染全局变量,而后者会形成一个属于模块自身都作用域,所有都变量以及函数只能自身能访问
  • 模块内部会有一个module对象用于存放当前模块信息,module.exports用来指定对外暴露哪些内容
  • 模块使用require进行方法导入

(2)ES6 Module

  • ES6 Module也是把每个文件作为一个模块,每个模块拥有自身都作用域,不同是导入,导出语句。import 和 export 也作为保留关键字加入了进来,作为导入导出关键字。
  • 导出有两种导出方式:命名导出和默认导出

(3)AMD

  • 它是有js社区提出都专注与浏览器端模块化都标准,它与之前两种方式都模块最大都区别是它是异步都。

  • 在AMD中使用define函数来定义模块,它可以接受三个参数。第一个参数是当前模块都id,相当于模块名。第二个参数是当前模块都依赖,第三个参数用来描述模块都导出值,可以是函数或对象。如果是函数则导出都是函数都返回值;如果是对象则导出对象本身。如果在当前模块中需要向外部导出成员,可以通过 return 的方式实现。

    // AMD 定义模块
    define([], function() {
      return {}
    })
    

(4)UMD

  • 严格来说UMD是一组模块形式都集合。通用模块标准它都目标是使一个模块能运行在各种环境下

如何开始一个webpack工程

前提条件

Webpack 对 Node.js >版本有一定要求,推荐使用Node.js的LTS(long Term Suppor 长期维护)使用新版本的node和新版本的webpack对性能优化有很大提升,相对于老版本,最大提速可达90%。所以推荐使用最新的稳定版本。

安装

  如果采用全局安装,那么在与他人进行协作的时候,由于每个人系统中webpack的版本不同,可能会导致输出结果不一致。部分依赖于webpack的插件会调用项目中webpack的内部模块,这种情况下仍然需要在本地安装,而如果本地和全局都有,则会造成混淆

所以这里我们选择在工程内部安装Webpack的方式。首先在桌面创建一个项目并初始化项目

mkdir webpackDemo 
cd webpackDemo
npm init 或者 # yarn init

接下来执行安装Webpack的命令

npm install webpack webpack-cli --save-dev

  这样就安装好了,webpack是我们要用的核心模块,webpack-cli是命令行工具。查看是否安装成功可以使用npx webpack -v; npx webpack-cli -v;如果显示版本号即安装成功; 为啥使用npx呢?因为我们把webpack安装到了本地,因此无法直接在命令行直接使用webpack命令,npx会帮助我们在当前项目的node_modules目录里面去找webpack。

打包第一个应用

首先我们在工程根目录创建index.html, src文件夹;并在src文件夹创建index.js文件和hello-world.js文件

touch index.html
mkdir src
cd src
touch index.js
touch hello-world.js

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>My first webpack app</title>
  </head>
  <body>
    <script src="./dist/bundle.js"></script>
  </body>
</html>

index.js

import HelloWorld from "./hello-world";

document.write("My first webpack app <br />");
HelloWorld();

hello-world.js

export default function() {
  document.write("Hello World");
}

这时候我们使用命令

npx webpack

在打开index.html文件就能看到页面上会显示

My first webpack app
Hello World

配置webpack

首先我们要知道webpack并不能直接打包你的项目,如果你能直接打包,其实是webpack团队默认做了配置文件,现在我们自己来写一个基础的配置文件,webapck默认配置文件为webpack.config.js,我们在根目录来创建这个文件,并添加代码:

module.exports = {
  entry: "./src/index.js",
  output: {
    filename: "bundle.js"
  },
  mode: "development"
};

我们平时使用react 或者 vue的时候常用的是npm run 命令来进行webpack打包,那么接下来我们配置npm script

在package.json文件中

"scripts": {
    - "test": "echo \"Error: no test specified\" && exit 1",
    + "build": "webpack",
  }

现在让我们删掉dist打包文件重新执行命令

npm run build

我们看到webpack执行了打包命令,重新生成了dist打包文件

webpack-dev-server

每次修改文件都要重新执行打包,感觉开发调试效率并不高。以往只要编辑项目,刷新就行,现在多了一步打包。那怎么优化呢? 社区为我们提供了一个快捷的本地开发工具--webpack-dev-server。用一下命令进行安装:

npm install webpack-dev-server --save-dev

安装完成我们在package.json文件中添加script配置文件

"scripts": {
     "build": "webpack",
   + "dev": "webpack-dev-server"
  }

最后我们还需要对webpack.congif.js进行配置

module.exports = {
  entry: "./src/index.js",
  output: {
    filename: "bundle.js"
  },
  mode: "development",
  devServer: {
    publicPath: "/dist" // 在后面会说publicPath是什么意思
  }
};

  webpack-dev-server可以看成是一个服务者,它对主要任务是接受浏览器对请求,然后将资源返回。当启动服务当时候,会先让webpack进行模块打包并将资源准备好(这里当资源文件就是bundle.js)当webpack-dev-server接受浏览器请求时,它会先进行url地址校验。如果该地址是资源服务地址(我们配置当publicPath),就会从webpack打包中寻找该资源并返回给浏览器。反之,如果请求地址不属于资源服务地址,则直接读取硬盘中当源文件将其返回,所以这就是为什么有时候你打开index.html文件会返回源文件当原因。

接下来我们执行

npm run dev

这时候命令行提示报错了Error: Cannot find module 'webpack-cli/bin/config-yargs' 这是由于webpack-cli的新版本对webpack-dev-server版本的不兼容,我们之前对版本是:

"webpack": "^5.6.0",
"webpack-cli": "^4.2.0",
"webpack-dev-server": "^3.11.0"

我们先把webpack-cl删除,再安装指定版本

npm uninstall webpack-cli -D
npm install webpack-cli@^3.3.12 --save-dev

这时候我们在执行命令会发现webpack正常运行了。 打开本地ulr就可以看到页面正常显示了。

或者直接使用:

"scripts": {
   - "dev": "webpack-dev-server"
   + "dev": "webpack-dev-server --open"
  }

总结

  看完Webpack 基础篇我们对webpack有了基本的了解,知道它是什么,它能做什么,如何使用webpack进行项目开发,知道了webpack-dev-server的基本用法。那么基础知识已经搭建完成,接下来准备进入Webpack 进阶篇,开始了解如何使用和编写模块,进一步加深对webpack的理解~

相关系列

Webpack 进阶篇