-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
模块化 以及 webpack如何处理模块化 #7
Comments
最近遇到一个问题。假如我需要用到 lodash 里的 clonedeep 方法,下面两种引入有何区别? tip: 这个问题涉及到以下的知识点: 前端模块化有哪些方案,区别是什么我们熟知的模块化方案有:AMD,CMD,Commonjs,ES6。其中AMD,CMD 分别是requirejs和seajs在推广中延伸出来的规范。现在大家比较常用的是Commonjs,ES6这两种方案。所以我们着重分析这两种 Commonjs我们来看第一个例子 // main.js
console.log('加载了main 模块')
var add = require('./add.js')
console.log('add 模块加载完毕')
console.log(add(1,1))
var square = require('./square.js')
console.log(square.square(3)) // add.js
console.log('加载了add模块')
var add = function(x,y) {
return x + y
}
module.exports = add // square.js
console.log('加载了square模块')
var multiply = require('./multiply')
var square = function(num) {
return multiply.multiply(num, num)
}
module.exports.square = square // multiply.js
console.log('加载了 multiply 模块')
var multiply = function(x, y) {
return x * y
}
module.exports.multiply = multiply 我们运行main.js 打印如下: 加载了main模块 -> 加载了 add 模块 -> add 模块加载完毕 -> 2 -> 加载了 square 模块->加载了multiply 模块 -> 9 从运行结果可以看出,commonjs在加载模块时的基本准则是 接下来我们来看看另外的一个例子 // count.js
var count = 3
function incCount() {
count++
console.log('in count.js count = ', count)
}
module.exports = {
count: count,
incCount: incCount
} // main.js
var mod = require('./count')
console.log(mod.count)
mod.incCount()
console.log(mod.count) 运行main.js 打印结果如下 3 -> in count.js count = 4 -> 3 这里的count是基本类型,如果是对象呢?我们来看下 // count.js
var counter = { value: 3 }
function incCount() {
counter.value++
}
module.exports = {
counter: counter,
incCount: incCount
} // main.js
var mod = require('./count')
console.log(mod.counter)
mod.incCount()
console.log(mod.counter) 运行main.js 结果如下 {value: 3} -> {value: 4} 从以上两个例子可以看出commonjs的另外一个特性 接下来再看考虑一种比较特殊的情况,循环引入 // main.js
const a = require('./a.js') // a.js
console.log('a is start')
let b = require('./b.js')
console.log('in a, bvalue is %j', b.bValue)
exports.aValue = 'this is a value'
console.log('a is end') //b.js
console.log('b is start')
let a = require('./a.js')
console.log('in b, a value is %j' , a.aValue )
exports.bValue = 'this is b value'
console.log('b is end') 运行main.js 打印结果如下 开始加载 main 模块 -> a is start -> b is start -> in b, a value is undefined -> b is end
-> in a, bvalue is 'this is b value' -> a is end -> main 模块执行完毕 上面的循环逻辑如下所示 我们再来看一个循环引用的例子 // a.js
console.log('a starting')
exports.done = false
const b = require('./b.js')
console.log('in a, b.done = %j', b.done)
exports.done = true
console.log('a done') console.log('b starting')
exports.done = false
const a = require('./a.js')
console.log('in b, a.done = %j', a.done)
exports.done = true
console.log('b done') 运行a.js 结果如下 a starting -> b starting -> in b, a.done = false -> b done -> in a,b.done = ture -> a.done 从上述例子可以得出以下结论
ES6推荐一个文档链接,关于ES6模块化的实现 我们先来看最基本的 // 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>ES6</title>
</head>
<body>
<h1>content</h1>
<script src="vender/main.js" type="module"></script>
</body>
</html> // main.js
console.log('加载了main模块')
import { add } from './add.js'
console.log(add(1,1))
import {square} from './square.js'
console.log(square(3)) //add.js
console.log('加载了 add 模块')
var add = function(x, y) {
return x + y
}
export {add} // multiply.js
console.log('加载了 multiply 模快')
var multiply = function(x, y){
return x * y
}
export {multiply} // square.js
console.log('加载了 square 模块')
import { multiply } from './multiply.js'
var square = function(num) {
return multiply(num, num)
}
export {square} 运行 index.html 页面,结果如下 加载了 add 模块 -> 加载了 multiply 模快 -> 加载了 square 模块 -> 加载了main模块 -> 2 -> 9 在mainjs里面, import { add } from './add.js' 和 import { square } from './square.js' 调换位置呢? 结果如下 加载了 multiply 模快 -> 加载了 square 模块 -> 加载了 add 模块 -> 加载了main模块 -> 9-> 2 由此,我们可以得出第一条结论 我们再来看另外一个例子 // 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>Document</title>
</head>
<body>
<h1>contentd</h1>
<script src="main.js" type="module"></script>
</body>
</html> // main.js
import {counter, incCount} from './counter.js'
console.log(counter)
incCount()
console.log(counter) let counter = 3
function incCount() {
counter++
}
export {counter, incCount} 我们运行,结果如下 3 -> 4 由此我们可以得出以下结论 我们再来看下ES6中循环引入的demo // 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>Document</title>
<script src="./main.js" type="module"></script>
</head>
<body>
</body>
</html> // main.js
console.log('main.js is start')
import { aValue } from './a.js'
console.log('in main, a value is ', aValue)
console.log('mian.js is end') // a.js
console.log('a is start')
import { bValue } from './b.js'
var aValue = 'this is a value'
console.log('in a, b value is ', bValue)
export { aValue } // b.js
console.log('b is start')
import { aValue } from './a.js'
console.log('in b, a value is ', aValue)
let bValue = 'this is bValue'
export { bValue } 运行,结果如下 b is start -> in b, a value is undefined -> a is start -> in, a b value is this is bValue ->
main.js is start -> in main, a value is this is a value -> mian.js is end 上述引入关系如下图所示 webpack如何处理模块化我们知道ES6适用于浏览器端,而Commonjs适用于node。那为什么我们在浏览器端也可以用Commonjs呢? https://github.com/QiandaoLakeYY/blog_code/blob/master/module/webpack4/simpleWebpack.js 简单来说就是首先确定好模块之前的先后引入关系,然后变成数组传递到匿名函数里进行执行 建议把上面这个函数看懂,有利于之后的理解 建议在编译好的文件里面进行debug,一步一步来看。会比较清晰 结合上面的例子,假如我们把变量都引入了。但是没有都用呢? import { es6_name, es6_desc } from './module.js'
import { common_name, common_desc } from './common'
console.log(es6_name)
console.log(common_name) 然后 运行 npm run build-pro 我们看下编译好的文件,你会发现 es6 模块里的没有用到的变量已经被去掉了。但是commonjs里的还在。这是为什么呢? ES6 是在编译时候就行加载的,所以能进行静态分析,webpack会在这一过程中加入tree-shaking,能去除没用的变量。而Commonjs是在运行时,不能进行进行静态分析。所以不能去掉 TIPS: 回到最开始的问题。其实第一种和第二种写法效果是一的。如果要做到不引入全部,那么可以用下面的写法 const cloneDeep = require('lodash/cloneDeep') or import cloneDeep from 'lodash/cloneDeep' 参考https://juejin.im/post/5a2e5f0851882575d42f5609 |
No description provided.
The text was updated successfully, but these errors were encountered: