「千锋教育 古艺散人」 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