五个概念

五个概念:

  • 入口entry
    • 定义分析依赖的入口文件,类似于vue的main.js,从入口文件开始解析文件依赖关系,并将其打包
  • 出口output
    • 打包的产物,产出到哪里,以及产出的文件名
  • loader

    • 针对某类型文件使用的转换。
      1. module: {
      2. rules: [
      3. # 当碰到「在 require()/import 语句中被解析为 '.txt' 的路径」时
      4. # 在打包之前,先使用 raw-loader 转换一下
      5. { test: /\.txt$/, use: 'raw-loader' }
      6. ]
      7. }
  • 插件plugin

    • 插件则可以用于执行范围更广的任务。插件的范围包括,从打包优化和压缩,一直到重新定义环境中的变量
  1. plugins: [
  2. new HtmlWebpackPlugin({template: './src/index.html'})
  3. ]
  • 模式
    • 生产production时、开发development时
  1. module.exports = {
  2. mode: 'production'
  3. };

从场景中学配置

webpack核心: 是一个模块打包器
和传统的html文件里手动引入各资源相比,html文件作为管理方;webpack将一切资源视为模块,在webpack这个炼丹炉里,模块之间可以相互调用,比如css文件引用css文件,js文件引用css文件
这种能力的实现使得我们可以在html上直接生成一个节点,之后的所有操作,都可以通过模块打包器,将代码引用的图片、css、js、dom整理好,直接挂载在这个节点上。最终页面得以呈现
期间我们解决了

  • js文件相互引用的问题,而不是将所有js放到一个html文件里,有命名冲突和变量被直接修改的风险 (模块化)
  • ide的代码变化浏览器就得以变化的livereload or hmr
  • less

js文件的模块化

1、一个空文件夹,npm init 初始化后 添加以下配置
需要的条件:

  1. # package.json
  2. "scripts": {
  3. "build": "webpack"
  4. },
  5. "devDependencies": {
  6. "webpack": "^4.42.1",
  7. "webpack-cli": "^3.3.11"
  8. }

2、按照如下文件结构,创建文件

  1. ├── dist
  2. └── index.html # <script src="main.js"></script>
  3. ├── src
  4. ├── index.js # 默认的根文件
  5. └── print.js # index.js 引用了 print.js
  6. └── package.json

3、开始打包 npm run build
就可以看到 /dist文件夹下面自动生成了main.js文件,该文件是以index.js为入口将其依赖的所有文件打包后生成的main.js(默认压缩)

以上便是最简单的一个入门使用了
但是和我们平时使用脚手架如vue等,对比起来我们还需要做的:

  • 不依赖约定配置,自己定义入口出口文件 => entry\output字段
  • html里引用打包后的js,能不能手动添加改为自动?即打包生成js后自动插入html中

=> plugin: HtmlWebpackPlugin

  • dist文件只存在实际项目用到的,多余的每次打包时会清理掉

=> plugin: clean-webpack-plugin

  • 管理资源:css的加载引用 => loader: style-loader\css-loader
  • 开发时追踪错误和警告:devtool: ‘inline-source-map’
  • 修改代码后自动编译打包:”watch”: “webpack —watch”,
  • live reload打包文件变化后自动刷新浏览器:实时重新加载 webpack-dev-server
  • 自己传入html而不是js生成html:new HtmlWebpackPlugin template \raw-loader

其中模块化的写法可以:
1、es6 export default import xxx from ‘xxxx’
2、node的commonjs require 、 module.exports

3、处理图片

  1. // addImage.js
  2. let smallImg = document.createElement('img')
  3. # require 语法
  4. smallImg.src = require('../images/small.jpeg')
  5. document.body.appendChild(smallImg)

库:

  • url-loader

4、处理css文件

  1. import '../styles/addImage.css' # 控制图片大小的css
  2. let smallImg = document.createElement('img')
  3. smallImg.src = require('../images/small.jpeg')
  4. document.body.appendChild(smallImg)

库:

  • css-loader:让 CSS 文件也支持 import,并且会解析 CSS 文件
  • style-loader:将解析出来的 CSS 通过标签的形式插入到 HTML 中

然而一股脑将css文件整合进js文件也是有弊端的,大量css文件会使得js变得臃肿
因此extract-text-webpack-plugin插件 可以将css文件打包为一个单独的文件

然后打包成单独的css文件之后 就 需要手动在html代码里 添加css的依赖,
所以需要插件 html-webpack-plugin , 将文件自动引入html里

  1. module.exports = {
  2. //...
  3. plugins: [
  4. // 我们这里将之前的 HTML 文件当做模板
  5. // 注意在之前 HTML 文件中请务必删除之前引入的 JS 文件
  6. new HtmlWebpackPlugin({
  7. template: 'index.html'
  8. })
  9. ]
  10. };

进阶

思考的问题:
1、分块打包 ( 常改动的和不常改动的第三方库分开打包,给不常改动的添加浏览器缓存
2、抽取公共代码 ==> CommonsChunkPlugin插件
3、按需加载
bundle 文件包含了我们全部的自己代码。但是当用户访问我们的首页时,其实我们根本无需让用户加载除了首页以外的代码
所以需要分割代码,按场景。首页必须的,切换到某个页面再重新加载的。。
==> 这个优化我们可以通过路由的异步加载来完成。

4、自动刷新
webpack-dev-server

5、别名

  1. module.exports = {
  2. resolve: {
  3. extensions: ['.js', '.css', '.json'],
  4. // 路径别名,比如这里可以使用 css 指向 static/css 路径
  5. alias: {
  6. '@': resolve('src'),
  7. 'css': resolve('static/css')
  8. }
  9. },
  10. // 生成 source-map,用于打断点,这里有好几个选项
  11. devtool: '#cheap-module-eval-source-map',
  12. }

一步步从零开始用 webpack 搭建一个大型项目
配wbpack最关键的是思路问题!为什么这样说呢?大家不会配,不是他因为他不会去查webpack和粘代码,更多的是他想不到,就是没整个工程化的思路
在**场景,我们遇到了什么样的问题,好,那我们需要怎么去处理它,然后最后一步是,来我教你配webpack

所以尽量 回溯到场景里 这样才能记住接口

webpack常用的loader、插件

  • css-loader:让 CSS 文件也支持 import,并且会解析 CSS 文件
  • style-loader:将解析出来的 CSS 通过标签的形式插入到 HTML 中
  • babel-loader 用于让 webpack 知道如何运行 babel
  • babel-core 可以看做编译器,这个库知道如何解析代码
  • babel-preset-env 这个库可以根据环境的不同转换代码
  • 抽取公共代码 ==> CommonsChunkPlugin插件
  • html-webpack-plugin , 将文件自动引入html里

require 和 import 的区别
=> 解析 bundle 如何加载模块的、webpack 如何实现的动态加载模块

我们使用的 require,是被 webpack 的api即webpack_require,打包之后产生的dist/bundle.js是一个立即执行函数,它是把所有模块捆绑在一起的一个巨型模块。

import:import 跟 require 的区别是,import 是动态加载只有在用到的时候才会去加载,而 require 只要声明了就会加载。
import原理:
import 去引用一个模块,除了正常的 bundle 之外,我们还可以看见一个 0.boundle.js(即动态加载的 index.css 模块)
动态模块加载逻辑:利用的 jsonp 的实现原理加载模块

参考资料

1、webpack:从入门到真实项目配置
2、一步步从零开始用 webpack 搭建一个大型项目
3、https://survivejs.com/webpack/foreword/