对webpack的理解,模块概念,loader, plugin, babel, tree-shake等的理解

webpack是javascript和相关文件的打包器。 将许多module打包成几个bundled assets。 代码拆分允许按需加载应用程序的一部分。 通过“加载器”,模块可以是 CommonJs、AMD、ES6 模块、CSS、image、JSON、Coffeescript、LESS ……以及您的自定义内容。

github源码参考

官方中文文档参考

模块概念

引自webpack:

Webpack 天生支持如下模块类型:

通过 loader 可以使 webpack 支持多种语言和预处理器语法编写的模块。loader 向 webpack 描述了如何处理非原生模块,并将相关依赖引入到你的 bundles中。 webpack 社区已经为各种流行的语言和预处理器创建了 loader,其中包括:

当然还有更多!总得来说,webpack 提供了可定制,强大且丰富的 API,允许在 任何技术栈 中使用,同时支持在开发、测试和生产环境的工作流中做到 无侵入性

怎么理解呢?

webpack会从入口文件开始,递归的构建一个依赖关系图,这个依赖图包含着应用程序中所需的每个模块,比如你的index.js里面import了其它的module

import 'a.js'

import 'b.css'

那么webpack会找到他们的依赖关系,找到了a.js模块,使用对应js的loader去解析处理成我们想要的输出,找到了b.css,用另一种css的loader去解析,在webpack解析的各个生命周期中会执行plugin中定义的各种操作。最后将所有模块打包为少量的 bundle。

Loader的概念

loader 用于对模块的源代码进行转换。loader 可以使你在 import 或 "load(加载)" 模块时预处理文件。因此,loader 类似于其他构建工具中“任务(task)”,并提供了处理前端构建步骤的得力方式。loader 可以将文件从不同的语言(如 TypeScript)转换为 JavaScript 或将内联图像转换为 data URL。loader 甚至允许你直接在 JavaScript 模块中 import CSS 文件!

plugin的概念

webpack 插件是一个具有 apply 方法的 JavaScript 对象。apply 方法会被 webpack compiler 调用,并且在 整个 编译生命周期都可以访问 compiler 对象。

ConsoleLogOnBuildWebpackPlugin.js

const pluginName = 'ConsoleLogOnBuildWebpackPlugin';

class ConsoleLogOnBuildWebpackPlugin {
  apply(compiler) {
    compiler.hooks.run.tap(pluginName, (compilation) => {
      console.log('webpack 构建正在启动!');
    });
  }
}

module.exports = ConsoleLogOnBuildWebpackPlugin;

compiler hook 的 tap 方法的第一个参数,应该是驼峰式命名的插件名称。建议为此使用一个常量,以便它可以在所有 hook 中重复使用

babel

  1. 可以帮我们把ES6转化成ES5
  2. 使用@babel/plugin-react-jsx,可以解析jsx代码,转化成React.createElement
    代码。

底层原理是先把js代码转成AST代码,然后再把AST转成目标代码。

<!DOCTYPE html>
<html>

<body>
  <div id="app"></div>
  <script src="https://unpkg.com/react@17/umd/react.development.js"></script>
  <script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
  <!-- Babel Script -->
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
  <script type="text/jsx">
      const app = document.getElementById('app');
      const jsxDom = <h1>Hello World</h1>;
      ReactDOM.render(jsxDom, app);
    </script>
</body>

</html>

几个常用的babel要理解:

@babel/core:Babel 的核心功能包含在 @babel/core 模块中,把js代码转成 { code, map, ast }

@babel/preset-env:一个智能预设,允许您使用最新的 JavaScript,而无需微管理目标环境需要哪些语法转换(以及可选的浏览器 polyfill)。 这既让你的生活更轻松,也让 JavaScript 包更小!获取您指定的任何目标环境并根据其映射检查它们以编译插件列表并将其传递给 Babel。

"browserslist": "> 0.25%, not dead"

@babel/preset-react:Babel 能够转换 JSX 语法

@babel/preset-typescript:将ts转js