《webpack实战、⼊门、进阶与调优》笔记
⽂中使⽤版本:webpack4.x
第⼀章:webpack简介
模块化思想:
按照特定的功能将其拆分为多个代码段,每个代码段实现⼀个特定的⽬标。你可以对其进⾏独⽴的设计、开发和测试,最终通过接⼝来将它们组合在⼀起。
模块化解决了哪些问题?
1. 依赖关系:通过导⼊导出语句
2. 减少服务器请求,⽹络开销:资源合并
3. 作⽤域污染:模块间作⽤域隔离
ES6模块标准应⽤阻⼒:
1. ⽆法code splitting(代码分割)和tree shaking(抖掉未使⽤代码)
2. npm模块⼤多CommonJS形式,浏览器并不⽀持,因此⽆法直接拿来⽤
3. 个别浏览器及平台兼容问题
因此,在使⽤模块化同时兼容浏览器,需要模块打包⼯具
对⽐同类打包⼯具,webpack优势:
1. ⽀持多种模块标准(AMD、CommonJS、ES6 module)
2. code splitting(代码分割)
3. 处理多类型资源(使⽤loader)
4. 社区⽀持
Tips:
webpack建议本地安装,避免了多个开发者之间版本不⼀致导致的问题
本地的webpack⽆法命令⾏直接使⽤“webpack”指令,⼯程内部只能使⽤npx webpack 的形式,后续简化
安装:
npm install webpack webpack-cli --save-dev
为什么要安装webpack-cli?
这⾥是引⽤
默认配置及⽂件:
⼊⼝src/index.js
出⼝dist/
配置⽂件fig.js
本地开发⼯具webpack-dev-server
Tips:
指令npm install 和 npm install --production区别
npm install: 会下载全部devDependencies 和 dependencies包
npm install --production: 只下载dependencies包
webpack-dev-server优势:
1. 令webpack打包:
它并不会做其他额外操作,所有webpack所需配置都要⾃⼰配置,包括所承载页⾯的index.html页⾯也需要⾃⼰加到项⽬
2. 作为web Server
打包结果放在内存中,不存在于项⽬dist⽂件夹中
webpack-dev-server还有个特性live-reload(⾃动刷新)
live-reload: ⾃动刷新页⾯,全部资源会重新下载⼀遍
hot-module-replace(模块热替换):不刷新页⾯,只局部更新,不会再下载其他⽆关资源(看起来更好?)
第⼆章:模块打包
CommonJS:
导出:
//  正确⽰例:
name:'calculator',
add:function(a, b){return a + b;}
}
// 等同于
exports.name ='calculator';
exports.add=function(a, b){return a + b;};
/
/  错误⽰例
exports ={
name:'calculator',
add:function(a, b){return a + b;}
}
// 原因:默认会添加
// var module = {
//    exports: {}
// }
// var exports = ports
// 如果对exports重新定义为对象,会⾃动解除exports和module间的关联关系
不要将ports与exports混⽤,因为有⼀个会被冲掉
在导⼊⼀个模块时,整个⽂件都会被调⽤⼀遍,虽然收到的模块对象是ports或exports出来的对象,但之后的代码也会被执⾏⼀遍
name:'calculator'
}
console.log('end')
require该模块后,console语句也会输出,但我们⼀般不推荐这么⽤,⽽是将它提前
使⽤const modA = require('moduleA')⽅式导⼊模块,如果只需要执⾏不需要导出对象(例如初始化操作),可以不使⽤const modA接收对象。
如上例,console.log(‘end’)会在第⼀次导⼊时输出,再次导⼊时不再输出,⽽是直接使⽤上次ports或exports的结果对象(值拷贝?)
require函数可接受表达式,可以利⽤这个特性进⾏动态加载模块
['modA','modB'].forEach(name =>{
require('./'+ name)
})
ES6 Module:
// calculator.js
export default{
name:'calculator',
add:function(a, b){return a + b;}
}
// index.js
import calculator from'./calculator.js'
const sum = calculator.add(2,3)
console.log(sum)// 5
export import 是ES6保留字,
CommonJS中module不是保留字,可以被重新定义使⽤
ES6 Module中默认开启严格模式,不论有没有在顶部添加"use strict"字样,所以ES5转ES6的代码时要注意
导出:
1. 命名导出
// 写法1:
export const name = ‘calculator’;
// 写法2:
const name = ‘calculator’;
export {name}
// 也可以export {name as 别名}
2. 默认导出
// 整个js⽂件模块只能有⼀个default导出
export default {
name: ‘calculator’
}
// 或者
export default ‘calculator’
导⼊:
1.  对于命名导出
name:'calculator',
add:function(a, b){
return a + b
}
}
导⼊时可以ES6解构导⼊(名称必须在export中存在,⼀⼀对应):
import{name, add}from'./calculator.js'
// 或者使⽤别名(如有的变量名已经被使⽤) import {name, add as addSum} from './calculator.js' add(3,4);
// 若使⽤别名,则⽂中add⽅法并不存在,使⽤别名进⾏调⽤如:addSum(3, 4)
也可以整体导⼊(减少对当前作⽤域的影响)
import*as别名from'./calculator.js'
别名.add(3,4);
2.  对于默认导出
export default{
name:'calculator',
add:function(a, b){
return a + b
}
}
导⼊时可以
import别名from'./calculator.js'
别名.add(3,4)
可以理解为
import{default as别名}from'./calculator.js'
别名.add(3,4)
3.  混合导⼊(命名导⼊+默认导⼊)
原生js和js的区别导出:
// react.js
export Component {
name:'comp1'
fn:function(){}
}
export default{
// code
}
导⼊:
import React,{Component}from'react'
Tips: 默认导⼊必须放最前,否则语法报错
复合导出
1. 对于命名导出,进⾏导⼊再导出
import{name, add}from'./calculator.js'
export{name, add}
可以合并为⼀⾏
/
/ a.js
export{name, add}from'./calculator.js'
2. 对于默认导出,则不能进⾏复合,可以理解为没有依附的变量名
import calculator from'./calculator.js'
export default calculator
CommonJS 与 ES6 Module对⽐
对⽐⾓度cjs esm
建⽴模块
依      赖            动态模块依赖,可以动态require(’./’ +
modName),模块依赖关系运⾏时确定
静态模块依赖,模块依赖关系编译时确定(⼀般理解为webpack打包过程
中,那时bundle代码还未在服务器中运⾏)
模块导⼊值拷贝变量映射
esm静态优势:
1. 打包时确定⽆⽤代码,减⼩体积
2. 模块变量类型检查
3. 编译器优化
值拷贝(cjs) 与 动态映射(esm)
值拷贝:只第⼀次获取值并存储,⽅法内不可改变值,外部可随意更改值
动态映射:每次获取值,值映射可⽅法内部改变值,外部不可更改
循环依赖
cjs对于循环依赖的处理,在依赖过程中先导出ports这空对象
如上⽂所说,ports是在模块顶部默认创建了module对象并添加属性exports:{},所以在代码未结束时就导出了该ports空对象,然后逐步继续执⾏。
esm输出的是undefined
esm利⽤动态映射的特性,可以对循环依赖进⾏控制,达到预期⽬的
做法:导出function实现延后执⾏,在function中通过开关标识进⾏阻断,第⼀次之后就进⾏切换标识状态,防⽌循环调⽤。结论: ES6 Module可以更好地⽀持循环依赖
⾮模块化⽂件:
对于对象绑定全局的,直接import即可
import'./jquery.min.js'
对于隐式绑定全局的,进⾏webpack打包后不会⾃动绑定到全局,因为外⾯加了⼀层function

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。