代碼分割從兩方面來說:React Lazy 和 webpack兩方面html
每次單頁應用打包出的文件又臭又長,是最蛋疼的事,瀏覽器刷個半天才出來網頁讓人巴不得找個地洞鑽進去,這種事很尷尬,讓人懷疑你這前端不專業前端
因此正題來了,這篇文章主要講解node
先上個最簡單的demo,App.js和Child.jsreact
// App.js
import React from 'react';
import Child from './Child';
function App() {
return (
<div className="App">
<Child />
</div>
);
}
export default App;
複製代碼
// Child.js
import React from 'react';
class Child extends React.Component{
render(){
return <div class="childClass">我是子組件啊</div>
}
}
export default Child;
複製代碼
就這個目錄結構,而後執行打包,打包以後以下:jquery
能夠看到Child組件被打包到了main.chunk.js裏面查找React文檔,能夠找到code split,那麼用React lazy來對Child組件作一下懶加載,仍是原來的組件App和Childwebpack
// App.js
import React, { lazy, Suspense } from 'react';
const Child = lazy(() => import('./Child'))
function App() {
return (
<div className="App">
<Suspense fallback={<div>Loading...</div>}>
<Child />
</Suspense>
</div>
);
}
export default App;
複製代碼
// Child.js
import React from 'react';
class Child extends React.Component{
render(){
return <div class="childClass">我是子組件啊</div>
}
}
export default Child;
複製代碼
其實api來講很簡單,就兩句代碼,這就實現了懶加載es6
import React, { lazy, Suspense } from 'react';
const Child = lazy(() => import('./Child'))
複製代碼
但是源碼裏能夠注意到還有一個Suspense,並且不用Suspense的話,瀏覽器會給出一個提示:web
從錯誤提示來看,lazy非要搭配Suspense使用了。那麼Suspense是何方神聖呢?能夠試想一下,既然是懶加載,那麼當Child還未加載完成以前,這個視圖怎麼辦?api
bingo!Suspense就是爲了處理這個的,讓視圖更友好,爲懶加載組件作優雅降級,它叫加載指示器
好的,那已經加上lazy了,執行打包吧瀏覽器
閱讀React lazy的官方文檔。發現lazy傳入一個函數,並且此函數須要返回一個Thenable,那麼當沒有返回Thenable的時候會怎麼辦呢?
發現瀏覽器掛了。。。這只是試下異常狀況,因此最好仍是按照React的官方文檔去操做吧webpack的代碼分離有三種方法:
此章節講解如何一個ui庫,解構導入let { Button } = ui;只導入Button
這也是老生常談的antd的import { Button } from 'antd',只導入Button問題
先上個反面教材吧
// index.js
import { mainAdd } from './main';
console.log(mainAdd(1, 2));
複製代碼
// main.js
const mainAdd = (a, b) => {
return a + b;
}
const mainMultiple = (a, b) => {
return a * b;
}
export {
mainAdd,
mainMultiple
}
複製代碼
webpack.config.js的配置entry就只配置index.js,來webpack打包一把
血崩啊,明明只是import了mainAdd,mainMultiple咋還打包進去了好的,反面教材講完了,如今教你們如何修改,先修改一下文件目錄
// webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
mode: 'development',
entry: {
index: './src/index.js'
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist')
},
plugins: [
new HtmlWebpackPlugin()
],
module: {
rules: [
{
test: /\.js$/,
loaders: 'babel-loader',
include: path.join(__dirname, 'src'),
options: {
plugins: [
["import", { "libraryName": "main", "libraryDirectory": "../../src/main"}],
]
},
}
]
}
};
複製代碼
//index.js
import { mainAdd } from 'main';
console.log(mainAdd(1, 2));
複製代碼
// main目錄下的main-add.js
const mainAdd = (a, b) => {
return a + b;
}
export default mainAdd;
複製代碼
// main目錄下的main-multiple.js
const mainMultiple = (a, b) => {
return a * b;
}
export default mainMultiple;
複製代碼
好的,再來執行一次打包,發現只打包進了mainAdd,而mainMultiple沒有打包進去。
總結一下,主要用到一個babel的知識點
options: {
plugins: [
["import", { "libraryName": "main", "libraryDirectory": "../../src/main"}],
]
},
複製代碼
libraryName指代的是import { mainAdd } from 'main'這裏的main -> 庫名,libraryDirectory是main下面的哪一個文件夾。好比antd/lib/button,這裏libraryDirectory配置的是lib,這裏默認是指向node_modules下的。我是放在src/main目錄下,因此這裏配置爲"../../src/main"
這個就很少說了,你們用的都比較多
仍是老習慣,先來個反面教材
// index.js
import _ from 'lodash';
import { each } from 'jquery';
console.log(
_.join(['index', 'module', 'loaded!'], ' ')
);
複製代碼
// main.js
import { each } from 'jquery';
let arr = ['zhangsan', 'lisi'];
each(arr, (idx, item) => {
console.log(item);
})
複製代碼
// webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
mode: 'development',
entry: {
index: './src/index.js',
another: './src/main.js'
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist')
},
plugins: [
new HtmlWebpackPlugin()
],
module: {
rules: [
{
test: /\.js$/,
loaders: ['babel-loader'],
include: path.join(__dirname, 'src')
}
]
}
};
複製代碼
兩個入口,打包一把
又血崩了,發現index.bundle.js打包進了jquery,another.bundle.js也打包進了jquery,能夠打開兩個bundle.js進去查找下jquery看看是否打包進去。那麼理想狀態下,應該是一份jquery,一份index,一份main,三份代碼。用官方文檔SplitChunksPlugin來試一把,index.js main.js webpack.config.js代碼幾乎不變。
// webpack.config.js中加上一項配置
optimization: {
splitChunks: {
chunks: 'all'
}
}
複製代碼
再打包一下
發現公共庫被提取出來了,index和another兩個文件只包含的業務代碼看一下chunk的裏面的代碼,發現只有verdors~other~index.bundle.js裏面有require("jquery"),而vendors~index.bundle.js裏面是直接用jquery的,並無引入jquery源碼
說明咱們的效果已經達到了。
至此四個功能已經講完了,本身寫個demo來演練下吧,有問題能夠加我微信demo0808