导出: export 语法
具名导出: export const name = 'huhua', export 变量, export { name as 改个名导出 }
默认导出: export defalut 你想导出的变量或者确定值; 模块挂载 default 属性上
导入: import 语法
导入具名模块: import { name } from './info.js'
导入默认模块: import Name from './infoDefault.js'
整体导入(当模块导出多个变量时): import * as ModuleObj from './info.js'
复合导入: import XXX, { ooo } from 'module'
...不说了
自执行导入: import './autoDo.js'
webpack读书小结
本篇主要是针对 webpack 文档的读书笔记, 以目录的形式展现, 旨在对 webpack 有个全局的了解...使用的时候不至于那么陌生emm...持续更新中ing
1.webpack简介
学一个知识点或者某一领域的内容, 遵守这个
知识点
是什么(what); 为什么用它(why); 怎么用它(how); 什么场景下用它(who); 使用时候的注意事项,坑点(when),当然这是事后总结...这是我一贯的学习习惯2.模块简介
webpack要处理的对象: 模块 这里主要介绍一下主流的模块化标准: CommonJS 规范和 ESModule 规范, 以及他们的特性
js文件即模块
导出: 模块内部有个 moudle 对象(记录每个模块的状态), 有个exports属性,用来导出 module.exports(他也是一个引用) = {}, 或者exports.xxx = ooo(exports引用module.exports)
导入: require('./module.js') require(): 它是一个函数, 执行()中的路径参数, 从而去执行路径模块文件的内容 再次调用(module.loaded = true): 直接去上次调用后缓存的结果
作用域: 模块自身
导出: export 语法 具名导出: export const name = 'huhua', export 变量, export { name as 改个名导出 } 默认导出: export defalut 你想导出的变量或者确定值; 模块挂载 default 属性上
导入: import 语法 导入具名模块: import { name } from './info.js' 导入默认模块: import Name from './infoDefault.js' 整体导入(当模块导出多个变量时): import * as ModuleObj from './info.js' 复合导入: import XXX, { ooo } from 'module' ...不说了 自执行导入: import './autoDo.js'
1.加载方式: CommonJS: 在代码运行时去查找,运行模块依赖文件(动态的) ESModule: 在代码解析,编译阶段查找模块依赖文件(静态的, 针对这一特性: 便有了tree shaking等一系列优化措施)
2.导入结果: CommonJS: 导入的是一个模块执行结果的拷贝 ESModule: 导入的是一个模块属性的只读引用
3.循环依赖解决: 项目太大时, 代码可能存在隐式的模块依赖循环引用 比如: a.js依赖b.js, b.js又依赖a.js CommonJS: 执行逻辑: a -> b(引入a: 直接导出a,未执行完: 空{}, 继续执行b) -> b 执行完在执行 a 解决: 模块是值拷贝, 无法解决, 只能提前返回一个{} ESModule: 执行逻辑: a -> b(引入a: 直接导出a,未执行完: undefined, 继续执行b) -> b 执行完在执行 a 解决: 因为模块是动态引用, 利用这个特性可以解决
npm: js 的工具包管理器
webpack模块打包结果大致结构
3.webpack输入和输出
webpack会从入口文件 entry 所指文件开始检索, 将具有依赖关系的模块生成一颗依赖树, 最终得到一个 chunk, 即打包好的 bundle.js文件
输入: 入口配置
// 多页应用 module.exports = { entry: { page1: './src/page1.js', page2: './src/page2.js', page3: './src/page3.js', vendor: ['vue', 'vue-router'] // 公共第三方模块, 需配合optimization.splitChunks } // 打完包后, 各自的 html 引入对应的 chunk 即可 }
4.webpack 预处理器 loader: 处理各类资源文件模块
我们一个工程目录下往往并不是只有 js 文件, 还有其他资源文件, 如 html, css,图片,字体等... 他们又不是标准的模块, 那我们打包怎么处理, 所以引入预处理器 loader 来负责.
loader 简介
loader本质上是一个函数
loader 配置
项目常用 loader
// babel-loader 支持.babelrc 文件读取 babel 配置, 可以抽离出来 { "presets": [ ["env", { "modules": false, "targets": { "browsers": ["> 1%", "last 2 versions", "not ie <= 8"] } }], "stage-2", ], "plugins": ["transform-runtime"] } // 也支持 babel.config.js module.exports = { presets: [ '@vue/app' ] }
import aHtml from './a.html' document.write(aHtml)
import imgPath from './images/xx.png' console.log(imgPath) // data:image/png base64字符
自定义的 loader 函数
loader API
5.webpack 插件 Plugins
Plugins 用于 bundle 文件的优化,资源管理和环境变量注入,在整个构建过程起作用
6.代码分片
也就是将打包的代码分成小块, 在访问页面时加载必要的资源, 其他资源可以延迟加载或者渐进式的加载... 说了那么多, 即
按需加载
必要代码怎么去划分和管理代码块
// SplitChunks module.exports = { entry: './index.js', output: { filename: 'bundle.js', publicPath: '/dist/' }, optimization: { splitChunks: { chunks: 'all' } } }
// optimization.splitChunks默认配置 splitChunks: { chunks: "async", // 工作模式: 提取异步 chunk // chunk匹配条件 minSize: 30000, minChunks: 1, maxAsyncRequests: 5, maxInitialRequests: 3, automaticNameDelimiter: '~', // 分隔符 name: true, // chunk 分离规则cacheGroups && default cacheGroups: { vendors: { // 作用于所有node_modules中符合条件的模块 test: /[\/]node_modules[\/]/, priority: -10 }, default: { // 作用于被多次引用的模块 minChunks: 2, priority: -20, reuseExistingChunk: true } } }
生产环境打包配置注意
项目构建打包优化
happypack替换初始的loader. 开启多线程进行转译,意味着要消耗 cpu 资源
ES6 Module依赖关系的构建是在代码编译时而非运行时。基于这项特性Webpack提供了tree shaking功能,它可以在打包过程中帮助我们检测工程中没有被引用过的模块,这部分代码将永远无法被执行到,因此也被称为“死代码”。Webpack会对这部分代码进行标记,并在资源压缩时将它们从最终的bundle中去掉
// 对 babel 编译的 AST 针对上述特性做处理 // 修改 AST
['@babel/preset-env', { module: false }]