为什么需要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

资源模块