webpack相关

本文全面介绍了Webpack的基础概念,包括entry入口设置、output输出路径、loader和plugin的作用,以及mode模式的应用。深入讲解了配置JS、Vue、JSX、CSS和HTML的处理,优化手段如HMR、缓存、oneOf和多进程打包。还涉及代码分割、预加载和性能优化策略,如兼容性处理、treeshaking和打包体积控制。

总结 Webpack

Webpack 基本概念

1. entry 入口
  • 以某个文件为入口开始打包
  • 分类
    • 单入口 String
      • 只会输出一个文件
    • 多入口 Array / Object
      • Array 只会输出一个文件
      • Object 会输出多个文件 ==> 多页应用(MPA)
2. output 输出
  • 打包后资源输出到哪里去
  • 输出的文件名叫什么
3. loader 加载器
  • webpack 本身只能识别 json、js 模块,其他模块一旦加载就会报错
  • 需要借助 loader 帮助 webpack 识别其它识别不了的模块
4. plugins 插件
  • loader 功能有限,要想做功能更加强大的工作交给插件
  • 比如在页面中自动引入打包生成的js/css, 压缩css, 拷贝文件等
5. mode
  • 模式:开发环境(development)和生产环境(production)
  • 提供一系列默认配置, 用于简化配置

Webpack 基本配置

1. 处理JS文件
  • eslint-loader
    • 在package.json中配置eslintConfig来指示eslint-loader到底要干什么事
    • enfore: ‘pre’ 优先执行
  • babel-loader
    • 在package.json中配置babel来指示babel-loader到底要干什么事
2. 处理Vue文件
  • vue-loader
3. 处理JSX文件
  • babel-loader
  • presets: [’@babel/preset-react’]
4. 处理CSS文件
  • 开发环境:创建style标签插入样式
    • style-loader
    • css-loader
    • postcss-loader
    • less-loader / sass-loader / stylus-loader
  • 生产环境:提取单独css文件,将来通过link引入
    • MiniCssExtractPlugin.loader(还需要配置插件 new MiniCssExtractPlugin)
    • css-loader
    • postcss-loader
    • less-loader / sass-loader / stylus-loader
5. 处理HTML文件
  • 目标: 自动引入打包生成的js/css
  • html-webpack-plugin
6. 处理图片/字体/音视频文件
  • url-loader / file-loader
  • limit: 10000 小于10kb一下的图片会被base64处理

Webpack 优化手段

1. 优化打包构建速度
HMR 热模块替换
  • 为什么要用?
    • 默认情况下,一旦修改了代码,全部代码重新编译刷新,速度慢(全体刷新)
  • 有什么作用?
    • 只更新修改的模块,其他模块不变(局部更新)
  • 怎么使用?
    • devServer: { hot: true }
    • new webpack.HotModuleReplacementPlugin()
  • 注意:
    • 默认情况下只有样式文件有HMR功能(style-loader),JS是没有的
  • 开启JS的HMR功能:
    • 手写JS代码 --> module.hot.accpet(‘模块路径’, () => {})
    • 在Vue使用 --> vue-loader
    • 在React使用 --> react-hot-loader
缓存
  • eslint和babel两个任务处理JS文件,时间一般会比较长,为了让其重新构建速度更快, 可以使用缓存。
  • eslint --> cache: true
  • babel --> cacheDirectory: true
  • cache-loader放置在要缓存loader的前面
  • 注意:一般只针对耗时长的任务:eslint-loader/babel-loader/vue-loader
oneOf
  • 作用:
    • 让模块只被一个loader处理,其他的就不看了(原本所有都会判断一下)
    • 能够提升打包速度
  • 注意:
    • eslint-loader: 处理js, 需要先执行, 将其定义在oneOf的外面
    • babel-loader: 处理js, 后执行, 将其定义在oneOf的内部
多进程打包
  • 过去: happyPack
  • 现在: thread-loader
  • 用法和cache-loader差不多,放在要使用loader前面
  • 作用:开启多进程处理前面的任务,提升打包速度
  • 注意:每个进程开启和通信都有开销,一般只针对耗时长的任务:babel-loader
2. 优化打包代码体积和性能
兼容性处理
  • JS
    • babel-loader presets: [’@babel/preset-env’] 问题就是只能编译语法, 不能处理新API
    • @babel/polyfill 做API兼容,问题是体积太大了
    • core-js 在@babel/preset-env基础上,增加了useBuiltIns: 'usage’来实现按需加载
    • 指定浏览器版本或占有率配置, 进一步减小打包文件: 只打包使用了且浏览器没有实现的
  • CSS
    • postcss-loader
    • 在package.json中指定browserslist来指示postcss-loader兼容性做到什么程度
tree shaking( 摇树)
  • 去除没有使用的JS代码
  • 必须使用ES6模块化(需要禁止@babel/preset-env转换ES6模块化语法 modules: false)
  • 开启webpack的生产模式(内部启用TerserPlugin,用来压缩JS代码的插件,tree shaking功能就是这个插件完成的)
  • 在package.json配置sideEffects来指定哪些文件需要进行tree shaking
code split 代码分割 / lazy loading 懒加载
  • 作用:
    • 抽取公共代码
    • 拆分多个文件,减少单个文件体积(避免单次请求时间过长)
  • 配置:
    • 多入口 + optimization
      • 将node_modules抽取成单独模块
      • 将多入口的公共模块也抽取成单独模块
    • 单入口 + optimization + import
      • 将node_modules抽取成单独模块
      • 动态导入语法import就能将某些文件抽取成单独模块
    • import()动态引入模块
      • 原生 JS: 在需要的回调函数中动态加载模块, import(模块).then()
      • Vue: () => import(’./Foo.vue’), 实现路由组件懒加载
      • React: Suspence +lazy(() => import(’./SomeComponent’)), 实现路由组件懒加载
preload 和 prefetch 预加载
  • 作用:
    • 让资源提前加载
  • 区别:
    • preload 让当前页面的要使用资源加载(延后加载)
    • prefetch 让后面要使用资源提前加载(当前不需要使用)
  • 使用:
    • import(/* webpackPrefetch: true */’./xxx’)
    • import(/* webpackPreload: true */’./xxx’) // 没有效果
    • 问题:兼容性较差
  • 使用Chrome团队提供的一个工具包: preload-webpack-plugin
    • npm i -D preload-webpack-plugin@next // 必须是最新的下一个版本
    • 对异步模块包使用: prefetch
    • 对同步模块包使用: preload
cache 缓存
  • hash

    • webpack每次构建都会生成一个新的且唯一的hash
    • 问题:只要webpack重新构建,所有文件的hash都会发生变化,缓存就会失效
  • chunkhash

    • 打包属于同一个chunk,就共享同一个hash
    • 问题:样式文件被css-loader打包js文件中,导致样式文件和js文件属于同一个chunk,共享同一个hash
    • 一旦样式文件发生变化,js文件也会变
  • contenthash

    • 根据文件的内容来成hash,所以只要文件内容不一样,hash就不一样
    • 问题:
      • 比如A模块有一个依赖,是B模块,那么A模块内部就会保存B模块hash值,
      • 一旦B模块发生变化,B模块的hash值就会变,导致A模块内部保存B模块hash值也发生改变
      • 此时A模块文件内容发生变化,它的hash值也会变
    • 解决:
      • runtimechunk: true 将A模块保存的B模块hash值存到runtime文件中,这样A模块内部就没有B模块的hash值了,就不会因为B模块的修改而修改
### Webpack 面试题整理 #### 1. Webpack 的核心概念是什么? Webpack 是一种模块打包工具,其核心目标是将 JavaScript 应用程序中的静态资源视为模块,并对其进行打包处理以便于浏览器使用。它的核心概念包括入口(Entry)、出口(Output)、Loader 和 Plugin[^4]。 - **入口(Entry)**: 定义应用程序的起点,通常是一个或多个 JavaScript 文件。 - **出口(Output)**: 指定打包后文件的输出位置和名称。 - **Loader**: 负责将非 JavaScript 文件转换为可被 Webpack 处理的形式,例如通过 `babel-loader` 将 ES6+ 语法转译为兼容性更好的代码[^2]。 - **Plugin**: 提供更强大的功能扩展能力,用于完成 Loader 无法实现的任务,如优化、压缩、清理旧包等操作[^3]。 #### 2. Webpack 中 Loader 和 Plugin 的区别是什么? Loader 主要负责文件的转换工作,能够使 Webpack 支持多种类型的文件加载与解析;而 Plugin 则侧重于对整个构建过程的功能增强,能够在特定的时间节点触发事件来修改构建流程或结果。简单来说: - **Loader**:专注于单个文件的转换,配置在 `module.rules` 下。 - **Plugin**:提供全局范围内的功能扩展,配置在 `plugins` 数组中[^2]。 #### 3. Webpack 的打包原理是什么? Webpack 通过对项目结构进行分析,识别出所有的依赖关系树,然后按照这些依赖逐步解析各个模块的内容。对于非标准的 JavaScript 文件(如 Sass 或 TypeScript),会利用指定的 Loader 进行预处理后再纳入到最终的打包产物之中。此外,在版本升级至 v3 后,Webpack 不仅承担了基础的打包职责,还进一步加强了针对性能方面的考量,比如懒加载策略的应用等[^1]。 #### 4. 如何实现按需加载? 借助 Webpack 自带的 Code Splitting 特性和动态导入语句 (`import()`) 可以轻松达成按需加载的效果。这种方式允许开发者根据实际需求只下载必要的部分而不是一次性获取全部内容,进而提升首屏渲染速度并减少不必要的网络请求开销[^4]。 ```javascript // 使用 import 实现异步加载组件 function loadComponent(path) { return import(`./components/${path}.jsx`); } ``` #### 5. 常见的 Webpack Plugins 有哪些? 一些常用的 Webpack 插件列举如下: - **HtmlWebpackPlugin**: 自动生成 HTML 文件并将所有生成的 JS/CSS 文件注入其中[^3]。 - **MiniCssExtractPlugin**: 把 CSS 提取到独立的文件里而非嵌入到 JS 中[^3]。 - **CleanWebpackPlugin**: 清除每次重新编译前遗留下来的旧版文件夹及其内部数据项。 --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值