「千锋教育 古艺散人」 webpack5 教程

为什么需要webpack

产生背景

项目中引入大量js文件会给网页加载带来很多问题。

首先是加载顺序,浏览器解析html的顺序是从上至下,引入第三方库时便会存在先后顺序问题,例如jQuery及其第三方库,其次,多个文件也会拖慢js文件载入速度,影响用户体验。

因此可以将多个js文件按照加载顺序整合成一个文件,既解决了先后顺序问题又提高了加载速度。

这样还是会有一些其他问题:

作用域:将所有的代码都直接打包到一个文件中,会使得所有变量成为全局变量,污染全局作用域。

模块化:例如第三方文件库lodash.js 只需要很少的几个功能,却需要将整个库引入项目,无法按需加载需要的模块,造成了资源浪费。

为了解决这些问题,使用立即调用函数表达式 IIFE 来创建独立作用域

变量被单独定义在函数内部,不再被挂载至全局window下

(function(){
   var name = '123';
})()
console.log(name)

也可以通过具名函数得到变量

var result = (function(){
    var name = '123';
    return name;
})
console.log(name);

这种方式会存在大量无用的代码,文件体积太大,影响构建和加载效率,此时出现了代码拆分,即模块化。

优化方案

commonJS

这是一种在nodeJS环境下(浏览器环境下无法直接使用)的解决方法,通过module.exports和require实现模块化。

// math.js
const add = (x, y) => x + y;
const minus = (x, y) => x - y;

module.exports = {
  add,
  minus,
};

// server.js
const math = require("./math");
console.log(math.add(1, 3));

requireJS

在浏览器下使用的,可以使类似commonJs的模块在浏览器运行,通过define和require实现

//add.js
const add = (x, y) => x + y;
// define([],第一个参数是依赖的其他模块,func,第二个参数是回调函数,是模块对外暴露的接口)
define([], function () {
  return add;
});

// main.js
// 第一个参数是依赖模块的数组,它访问参照的目录点在引用的html文件,注意相对路径的书写
// 第二个参数是回调函数,指向了define的第二个函数
require(["./add", "./minus"], function (add, minus) {
  console.log(add(1, 2));
});

// index.html
<!-- data-main:加载的入口js文件 -->
<script
      src="https://cdn.bootcdn.net/ajax/libs/require.js/2.3.6/require.js"
      data-main="./main.js"
></script>

ECMAScript

对于web项目,模块逐渐成为ECMAScript的标准,使用export和import实现。

// add.js
const add = (x, y) => x + y;
export default add;
<!-- 如果不加type,会报错Uncaught SyntaxError: Cannot use import statement outside a module,加上type="module"之后,会报错跨域,需要搭建一个本地的http server环境
Access to script at 'file:///D:/vscode/WebpackDemo/ECMAScript/add.js' from origin 'null' has been blocked by CORS policy-->
<script type="module">
    import add from "./add.js";
    console.log(add(1, 2));
</script>

webpack

可以实现打包JS应用程序,也可以扩展支持很多的静态资源打包,并同时支持ES的模块化和commonJS。

webpack与竞品的比较

parcel

配置简单,一般无需做其他的配置开箱即用。适合构建一个简单,可以快速运行的应用。

rollup.js

用标准化的格式编写代码,如ES6,通过减少无用的代码,尽可能的缩小包的体积。一般只能用来打包js。适合构建一个简单的类库,只需要导入很少的第三方的库。

Vite

是未来vue的搭建工具,可以完成开发,编译,发布,demo。Vite采用基于ESModule的构建方式,可以按需编译,支持模块热更新等。

webpack

适合复杂的,需要继承很多第三方库,需要拆分代码,需要使用静态资源文件,支持common.js,esModule的应用。

webpack除了可以引入js,还可以使用内置的资源模块asset modules来引入任何的其他类型资源。

开发准备

安装webpack

1.安装 Node.js

2.验证node版本 npm版本

3.npm init -y 初始化package配置文件

4.npm install webpack webpack-cli --save-dev 本地安装webpack及webpack-cli

自定义webpack配置

const path = require('path');

module.exports = {
    entry: './src/index.js', //入口文件
    output: { //输出配置
        path: path.resolve(__dirname, './dist'), //输出路径
        filename: 'bundle.js', //输出文件名
        clean: true, // 在生成文件之前清空 output 目录
    },
    mode: 'development', //webpack编译模式,区分生产测试环境
    devtool: 'inline-source-map' //精准定位代码行数,便于查看
};

插件

webpack在打包流程中产生的编译过程,可以借助插件实现某些功能。

html-webpack-plugin

安装插件:npm install html-webpack-plugin -D

配置插件

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    entry: './src/index.js', //入口文件
    output: { //输出配置
        path: path.resolve(__dirname, './dist'), //输出路径
        filename: 'bundle.js', //输出文件名
        clean: true, // 在生成文件之前清空 output 目录
    },
    mode: 'development', //webpack编译模式,区分生产测试环境
    devtool: 'inline-source-map', //精准定位代码行数,便于查看
    plugins: [new HtmlWebpackPlugin({
        template: "./index.html", // 基于template对应的文件打包生成html
        filename: "app.html",
        inject: "body", // script标签的生成位置
    })],
};

搭建开发环境

watch mode

打包实时更新,不需要手动重新执行打包的命令,当源代码改变时,会自动重新运行,打包新的文件。

npx webpack --watch

使用 webpack-dev-server

webpack-dev-server提供了一个基本的web server,并且具有live reloading(实时加载)的功能。不但能监测文件的变化重新编译,还能实现浏览器的自动刷新。 安装:

npm install webpack-dev-server -D

配置:

module.exports={
    ...
    devServer:{
      static:'./dist' //指定根目录
    },
}

启动:

PS C:\Users\L\Desktop\Local\webpack\01> npx webpack-dev-server
<i> [webpack-dev-server] Project is running at:
<i> [webpack-dev-server] Loopback: http://localhost:8080/, http://[::1]:8080/
<i> [webpack-dev-server] On Your Network (IPv4): http://192.168.110.24:8080/
<i> [webpack-dev-server] Content not from webpack is served from './dist' directory
asset bundle.js 170 KiB [emitted] (name: main)
asset app.html 254 bytes [emitted]
runtime modules 27.4 KiB 12 modules

资源模块