BootCDN - Bootstrap 中文网开源项目免费 CDN 加速服务 铂特优选
一、为什么要用webpack
一个简单的例子
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.21/lodash.core.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.0.2/js/bootstrap.min.js"></script>
<script src="js/city.js"></script>
<script src="js/goods.js"></script>
<script src="js/member.js"></script>
</head>
<body>
</body>
</html>
这是我们常见的一个页面,上面是第三方的类库,下面是我们项目的业务代码,绝大多数情况下,我们的业务代码是需要依赖第三方类库的 ,根据js在浏览器上的加载特性,所有的js代码是从上至下来加载的,因此如果我们的业务代码依赖到了上面的第三方类库,那么顺序一定不能颠倒,如果颠倒成下面这样,肯定就会报错,这样就会给我们编码造成很大的心智负担
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/city.js"></script>
<script src="js/goods.js"></script>
<script src="js/member.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.21/lodash.core.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.0.2/js/bootstrap.min.js"></script>
</head>
<body>
</body>
</html>
假设把所有用到的js代码按照正确的顺序合并到一个js文件中,肯定能解决这个问题,如下面这个例子,bundle.all.js 包含了所有的第三方类库和项目业务代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/bundle.all.js"></script>
</head>
<body>
</body>
</html>
但是这样又有了新的问题,作用域问题,文件太大,可读性差,可维护性弱
例如:jquery会给全局作用域 window 绑定window.$, lodash 会给window绑定window._ ,就连我们的业务代码也可能会给window绑定全局变量 window.member,这些变量会使window对象变的臃肿
在app.js中写一个立即调用的表达式,在表达式内部定义的变量在外部是访问不到的
;(function (){
var myName = "孙悟空"
})()
console.log(myName)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script src="js/app.js"></script>
</body>
</html>
这样就不会像一般用var定义的全局变量一样,挂在window上,不会污染window,可以解决作用域的问题。
如果我们想对外暴露这个变量
var myName = (function (){
var myName = "孙悟空"
return myName
})()
console.log(myName)
这种方法看似既解决了作用域问题,又可以对外暴露我们想暴露的变量,但是还有其他的问题,比如说,把所有的代码合在一起,就算修改一行代码,也得把整个文件重新编译加载
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/lodash.4.17.21.js"></script>
</head>
<body>
<script>
const str = _.join(['孙悟空','猪八戒','沙僧','唐僧','小白龙'] , '-')
console.log(str)
</script>
</body>
</html>
上面这种方法我们只使用了lodash的一个方法,却加载了整个的lodash.js文件,这个文件非常的大,如果能按需加载lodash.js中我们用到的方法就好了
二、代码的拆分
1.common.js模块化
我们创建 math.js
const add = (x, y) => {
return x + y
}
const minus = (x , y) => {
return x - y
}
module.exports = {
add,
minus
}
创建server.js 并且通过 require 导入 math.js
const math = require("./math.js")
console.log(math.minus(1 , 2))
console.log(math.minus(100 , 50))
这里我们得借助node.js的环境进行执行
但是我们的浏览器其实是不支持这种模块化的,它不识别require这种语法,我们通过html导入server.js来让浏览器执行server.js
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/server.js"></script>
</head>
<body>
</body>
</html>
可以看到在node.js环境可以执行的代码,在浏览器失效了
如何让浏览器支持 common.js的语法呢
创建add.js
const add = (x , y) => {
return x + y
}
// 第一个参数定义依赖了哪些模块 七二个参数是一个回调函数
define([] , function(){
return add
})
创建minus.js
const minus = (x , y) => {
return x - y
}
// 第一个参数定义依赖了哪些模块 七二个参数是一个回调函数
define([] , function(){
return minus
})
创建main.js
require(['./js/add.js' , './js/minus.js'] , function (add , minus){
console.log(add(5 , 6))
console.log(minus(100 , 50))
})
创建一个 html 应用main.js
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
// 这里的require.js 是一个第三方类库,通过data-main来应用我们创建的main.js
<script data-main = "./js/main.js" src="js/require.js"></script>
</body>
</html>
成功的实现在浏览器上识别 require 这种common.js的导入方法