mrbone / mrbone.github.io

0 stars 0 forks source link

antd split module #19

Closed mrbone closed 6 years ago

mrbone commented 6 years ago

babel-plugin-import

mrbone commented 6 years ago

Antd bundle split

我们在使用 antd 或者类似的第三方样式库的时候,往往需要将整个类库打包进我们的 bundle,其实我们只使用某些 component,antd 提供了另外一种按需加载的方式。


我们新建一个简单的react项目。

import React from 'react';
import ReactDOM from 'react-dom';

ReactDOM.render(<div></div>,document.getElementById('app'));

这个时候用 webpack build 一下。

Version: webpack 2.7.0
Time: 5860ms
    Asset    Size  Chunks                    Chunk Names
bundle.js  2.5 MB       0  [emitted]  [big]  main

这时未压缩的 bundle 大小是2.5MB,这时候我们安装 antd 并修改 index.jsx

yarn add antd
import React from 'react';
import ReactDOM from 'react-dom';
import {Button} from 'antd';

ReactDOM.render(<Button>click me</Button>,document.getElementById('app'));

我们再build一次。

Version: webpack 2.7.0
Time: 26905ms
    Asset     Size  Chunks                    Chunk Names
bundle.js  13.8 MB       0  [emitted]  [big]  main main

bundle 已经扩大到了接近14MB,而我们只是简单的用了一个 Button 控件而已。
为了解决加载代价过大的问题,antd 自己有一个按需加载的方案,借助 babel-plugin-import这个插件。

yarn add babel-plugin-import --dev

接着更改 .bablerc

{
  "presets":[
    "react",
    [
      "env"
    ]
  ],
+  "plugins": [
+    [
+      "import",
+      {
+        "libraryName":"antd"
+      }
+    ]
+  ]
}

这个时候我们在 build 一次。

Version: webpack 2.7.0
Time: 6822ms
    Asset     Size  Chunks                    Chunk Names
bundle.js  2.85 MB       0  [emitted]  [big]  main

这个时候 bunle 增加的体积也就只有 Button 组件的代码了。
但这个时候还有一个问题,我们的样式现在引入的是整个 antd 的样式。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <link rel="stylesheet" href="./node_modules/antd/dist/antd.css">
  <title>Redux-todo</title>
</head>
<body>
  <div id="app"></div>
  <script src="./dist/bundle.js" charset="utf-8"></script>
</body>
</html>

样式我们能不能按需加载呢?也很简单,我们只要将 bable-plugin-import 配置改下就行了。

{
  "presets":[
    "react",
    [
      "env"
    ]
  ],
  "plugins": [
    [
      "import",
      {
        "libraryName":"antd",
+        "style": "css"
      }
    ]
  ]
}

这个配置的作用是在引入 Button 组件的时候自动会去引入 Button 组件目录下的 style/css

import { Button } from 'antd';
ReactDOM.render(<Button>xxxx</Button>);

      ↓ ↓ ↓ ↓ ↓ ↓

var _button = require('antd/lib/button');
require('antd/lib/button/style/css');
ReactDOM.render(<_button>xxxx</_button>);

我们去 antd 对应目录下去检查下就能发现,其实 antd 是通过一个默认的 js 文件去引入对应的 样式文件。antd 默认是通过 less 编写的样式文件,这里图省事我直接引入的css文件。

//node_modules/antd/lib/button/style/css.js
'use strict';

require('../../style/index.css');

require('./index.css');

此时我们加入 css-loader,并且删掉之前在html文件中引入的全部antd样式。

//webpack.config.js
+{
+    test: /\.css$/,
+    loader: 'css-loader'
+}
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
-  <link rel="stylesheet" href="./node_modules/antd/dist/antd.css">
  <title>Redux-todo</title>
</head>
<body>
  <div id="app"></div>
  <script src="./dist/bundle.js" charset="utf-8"></script>
</body>
</html>

再运行一次 npm start, 我们就可以看到那可爱的小按钮仍然在页面上。


结语

babel-plugin-import是一个很好用的 plugin,我们在使用一些自己造的组件库也可以通过不同的配置去实现按需加载,具体的配置方法可以去看官方文档