帶你深度解鎖Webpack系列(進階篇)

三篇長文,帶你解鎖 Webpack ,希望讀完這三篇文章,你能夠對 webpack 的各項配置有一個更爲清晰的認識。

本文是第二篇,如果你還沒有閱讀《帶你深度解鎖Webpack系列(基礎篇)》,建議閱讀之後,再繼續閱讀本文。

本文會引入更多的 webpack 配置,如果文中有任何錯誤,歡迎在評論區指正,我會盡快修正。 webpack 優化部分放在了下一篇。

推薦大家參考本文一步一步進行配置,不要總是想着找什麼最佳配置,掌握之後,根據自己的需求配置出來的,就是最佳配置。

本文對應的項目地址(編寫本文時使用) 供參考:github.com/YvetteLau/w…

 

 

1. 靜態資源拷貝

有些時候,我們需要使用已有的JS文件、CSS文件(本地文件),但是不需要 webpack 編譯。例如,我們在 public/index.html 中引入了 public 目錄下的 jscss 文件。這個時候,如果直接打包,那麼在構建出來之後,肯定是找不到對應的 js / css 了。

public 目錄結構

├── public
│   ├── config.js
│   ├── index.html
│   ├── js
│   │   ├── base.js
│   │   └── other.js
│   └── login.html

現在,我們在 index.html 中引入了 ./js/base.js

<!-- index.html -->
<script src="./js/base.js"></script>

這時候,我們 npm run dev,會發現有找不到該資源文件的報錯信息。

對於這個問題,我們可以手動將其拷貝至構建目錄,然後在配置 CleanWebpackPlugin 時,注意不要清空對應的文件或文件夾即可,但是如若這個靜態文件時不時的還會修改下,那麼依賴於手動拷貝,是很容易出問題的。

不要過於相信自己的記性,依賴於手動拷貝的方式,大多數人應該都有過忘記拷貝的經歷,你要是說你從來沒忘過。

幸運的是,webpack 爲我們這些記性不好又愛偷懶的人提供了好用的插件 CopyWebpackPlugin,它的作用就是將單個文件或整個目錄複製到構建目錄。

首先安裝一下依賴:

npm install copy-webpack-plugin -D

修改配置(當前,需要做的是將 public/js 目錄拷貝至 dist/js 目錄):

//webpack.config.js
const CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = {
    //...
    plugins: [
        new CopyWebpackPlugin([
            {
                from: 'public/js/*.js',
                to: path.resolve(__dirname, 'dist', 'js'),
                flatten: true,
            },
            //還可以繼續配置其它要拷貝的文件
        ])
    ]
}

此時,重新執行 npm run dev,報錯信息已經消失。

這裏說一下 flatten 這個參數,設置爲 true,那麼它只會拷貝文件,而不會把文件夾路徑都拷貝上,大家可以不設置 flatten 時,看下構建結果。

另外,如果我們要拷貝一個目錄下的很多文件,但是想過濾掉某個或某些文件,那麼 CopyWebpackPlugin 還爲我們提供了 ignore 參數。

//webpack.config.js
const CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = {
    //...
    plugins: [
        new CopyWebpackPlugin([
            {
                from: 'public/js/*.js',
                to: path.resolve(__dirname, 'dist', 'js'),
                flatten: true,
            }
        ], {
            ignore: ['other.js']
        })
    ]
}

例如,這裏我們忽略掉 js 目錄下的 other.js 文件,使用 npm run build 構建,可以看到 dist/js 下不會出現 other.js 文件。 CopyWebpackPlugin 還提供了很多其它的參數,如果當前的配置不能滿足你,可以查閱文檔進一步修改配置。

2.ProvidePlugin

ProvidePlugin 在我看來,是爲懶人準備的,不過也別過度使用,畢竟全局變量不是什麼“好東西”。ProvidePlugin 的作用就是不需要 importrequire 就可以在項目中到處使用。

ProvidePluginwebpack 的內置插件,使用方式如下:

new webpack.ProvidePlugin({
  identifier1: 'module1',
  identifier2: ['module2', 'property2']
});

默認尋找路徑是當前文件夾 ./**node_modules,當然啦,你可以指定全路徑。

React 大家都知道的,使用的時候,要在每個文件中引入 React,不然立刻拋錯給你看。還有就是 jquery, lodash 這樣的庫,可能在多個文件中使用,但是懶得每次都引入,好嘛,一起來偷個懶,修改下 webpack 的配置:

const webpack = require('webpack');
module.exports = {
    //...
    plugins: [
        new webpack.ProvidePlugin({
            React: 'react',
            Component: ['react', 'Component'],
            Vue: ['vue/dist/vue.esm.js', 'default'],
            $: 'jquery',
            _map: ['lodash', 'map']
        })
    ]
}

這樣配置之後,你就可以在項目中隨心所欲的使用 $_map了,並且寫 React 組件時,也不需要 import ReactComponent 了,如果你想的話,你還可以把 ReactHooks 都配置在這裏。

另外呢,Vue 的配置後面多了一個 default,這是因爲 vue.esm.js 中使用的是 export default 導出的,對於這種,必須要指定 defaultReact 使用的是 module.exports 導出的,因此不要寫 default

另外,就是如果你項目啓動了 eslint 的話,記得修改下 eslint 的配置文件,增加以下配置:

{
    "globals": {
        "React": true,
        "Vue": true,
        //....
    }
}

當然啦,偷懶要有個度,你要是配一大堆全局變量,最終可能會給自己帶來麻煩,對自己配置的全局變量一定要負責到底。

3.抽離CSS

CSS打包我們前面已經說過了,不過呢,有些時候,我們可能會有抽離CSS的需求,即將CSS文件單獨打包,這可能是因爲打包成一個JS文件太大,影響加載速度,也有可能是爲了緩存(例如,只有JS部分有改動),還有可能就是“我高興”:我想抽離就抽離,誰也管不着。

不管你是因爲什麼原因要抽離CSS,只要你有需求,我們就可以去實現。

首先,安裝 loader:

npm install mini-css-extract-plugin -D

mini-css-extract-pluginextract-text-webpack-plugin 相比:

  1. 異步加載
  2. 不會重複編譯(性能更好)
  3. 更容易使用
  4. 只適用CSS

修改我們的配置文件:

//webpack.config.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
    plugins: [
        new MiniCssExtractPlugin({
            filename: 'css/[name].css'
            //個人習慣將css文件放在單獨目錄下
            //publicPath:'../'   //如果你的output的publicPath配置的是 './' 這種相對路徑,那麼如果將css文件放在單獨目錄下,記得在這裏指定一下publicPath 
        })
    ],
    module: {
        rules: [
            {
                test: /\.(le|c)ss$/,
                use: [
                    MiniCssExtractPlugin.loader, //替換之前的 style-loader
                    'css-loader', {
                        loader: 'postcss-loader',
                        options: {
                            plugins: function () {
                                return [
                                    require('autoprefixer')({
                                        "overrideBrowserslist": [
                                            "defaults"
                                        ]
                                    })
                                ]
                            }
                        }
                    }, 'less-loader'
                ],
                exclude: /node_modules/
            }
        ]
    }
}

現在,我們重新編譯:npm run build,目錄結構如下所示:

.
├── dist
│   ├── assets
│   │   ├── alita_e09b5c.jpg
│   │   └── thor_e09b5c.jpeg
│   ├── css
│   │   ├── index.css
│   │   └── index.css.map
│   ├── bundle.fb6d0c.js
│   ├── bundle.fb6d0c.js.map
│   └── index.html

前面說了最好新建一個 .browserslistrc 文件,這樣可以多個 loader 共享配置,所以,動手在根目錄下新建文件 (.browserslistrc),內容如下(你可以根據自己項目需求,修改爲其它的配置):

last 2 version
> 0.25%
not dead

修改 webpack.config.js

//webpack.config.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
    //...
    plugins: [
        new MiniCssExtractPlugin({
            filename: 'css/[name].css' 
        })
    ],
    module: {
        rules: [
            {
                test: /\.(c|le)ss$/,
                use: [
                    MiniCssExtractPlugin.loader,
                    'css-loader', {
                        loader: 'postcss-loader',
                        options: {
                            plugins: function () {
                                return [
                                    require('autoprefixer')()
                                ]
                            }
                        }
                    }, 'less-loader'
                ],
                exclude: /node_modules/
            },
        ]
    }
}

要測試自己的 .browserlistrc 有沒有生效也很簡單,直接將文件內容修改爲 last 1 Chrome versions ,然後對比修改前後的構建出的結果,就能看出來啦。

可以查看更多[browserslistrc]配置項(github.com/browserslis…)

更多配置項,可以查看mini-css-extract-plugin

將抽離出來的css文件進行壓縮

使用 mini-css-extract-pluginCSS 文件默認不會被壓縮,如果想要壓縮,需要配置 optimization,首先安裝 optimize-css-assets-webpack-plugin.

npm install optimize-css-assets-webpack-plugin -D

修改webpack配置:

//webpack.config.js
const OptimizeCssPlugin = require('optimize-css-assets-webpack-plugin');

module.exports = {
    entry: './src/index.js',
    //....
    plugins: [
        new OptimizeCssPlugin()
    ],
}

注意,這裏將 OptimizeCssPlugin 直接配置在 plugins 裏面,那麼 jscss 都能夠正常壓縮,如果你將這個配置在 optimization,那麼需要再配置一下 js 的壓縮(開發環境下不需要去做CSS的壓縮,因此後面記得將其放到 webpack.config.prod.js 中哈)。

配置完之後,測試的時候發現,抽離之後,修改 css 文件時,第一次頁面會刷新,但是第二次頁面不會刷新 —— 好嘛,我平時的業務中用不着抽離 css,這個問題擱置了好多天(準確來說是忘記了)。

3月8號再次修改這篇文章的時候,正好看到了 MiniCssExtractPlugin.loader 對應的 option 設置,我們再次修改下對應的 rule

module.exports = {
    rules: [
        {
            test: /\.(c|le)ss$/,
            use: [
                {
                    loader: MiniCssExtractPlugin.loader,
                    options: {
                        hmr: isDev,
                        reloadAll: true,
                    }
                },
                //...
            ],
            exclude: /node_modules/
        }
    ]
}

4.按需加載

很多時候我們不需要一次性加載所有的JS文件,而應該在不同階段去加載所需要的代碼。webpack內置了強大的分割代碼的功能可以實現按需加載。

比如,我們在點擊了某個按鈕之後,才需要使用使用對應的JS文件中的代碼,需要使用 import() 語法:

document.getElementById('btn').onclick = function() {
    import('./handle').then(fn => fn.default());
}

import() 語法,需要 @babel/plugin-syntax-dynamic-import 的插件支持,但是因爲當前 @babel/preset-env 預設中已經包含了 @babel/plugin-syntax-dynamic-import,因此我們不需要再單獨安裝和配置。

直接 npm run build 進行構建,構建結果如下:

 

webpack 遇到 import(****) 這樣的語法的時候,會這樣處理:

  • 以**** 爲入口新生成一個 Chunk
  • 當代碼執行到 import 所在的語句時,纔會加載該 Chunk 所對應的文件(如這裏的1.bundle.8bf4dc.js)

大家可以在瀏覽器中的控制檯中,在 NetworkTab頁 查看文件加載的情況,只有點擊之後,纔會加載對應的 JS

5.熱更新

  1. 首先配置 devServerhottrue
  2. 並且在 plugins 中增加 new webpack.HotModuleReplacementPlugin()
//webpack.config.js
const webpack = require('webpack');
module.exports = {
    //....
    devServer: {
        hot: true
    },
    plugins: [
        new webpack.HotModuleReplacementPlugin() //熱更新插件
    ]
}

我們配置了 HotModuleReplacementPlugin 之後,會發現,此時我們修改代碼,仍然是整個頁面都會刷新。不希望整個頁面都刷新,還需要修改入口文件:

     3. 在入口文件中新增:

if(module && module.hot) {
    module.hot.accept()
}

此時,再修改代碼,不會造成整個頁面的刷新。

6.多頁應用打包

有時,我們的應用不一定是一個單頁應用,而是一個多頁應用,那麼如何使用 webpack 進行打包呢。爲了生成目錄看起來清晰,不生成單獨的 map 文件。

//webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
    entry: {
        index: './src/index.js',
        login: './src/login.js'
    },
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: '[name].[hash:6].js'
    },
    //...
    plugins: [
        new HtmlWebpackPlugin({
            template: './public/index.html',
            filename: 'index.html' //打包後的文件名
        }),
        new HtmlWebpackPlugin({
            template: './public/login.html',
            filename: 'login.html' //打包後的文件名
        }),
    ]
}

如果需要配置多個 HtmlWebpackPlugin,那麼 filename 字段不可缺省,否則默認生成的都是 index.html,如果你希望 html 的文件名中也帶有 hash,那麼直接修改 fliename 字段即可,例如: filename: 'login.[hash:6].html'

生成目錄如下:

.
├── dist
│   ├── 2.463ccf.js
│   ├── assets
│   │   └── thor_e09b5c.jpeg
│   ├── css
│   │   ├── index.css
│   │   └── login.css
│   ├── index.463ccf.js
│   ├── index.html
│   ├── js
│   │   └── base.js
│   ├── login.463ccf.js
│   └── login.html

看起來,似乎是OK了,不過呢,查看 index.htmllogin.html 會發現,都同時引入了 index.f7d21a.jslogin.f7d21a.js,通常這不是我們想要的,我們希望,index.html 中只引入 index.f7d21a.jslogin.html 只引入 login.f7d21a.js

HtmlWebpackPlugin 提供了一個 chunks 的參數,可以接受一個數組,配置此參數僅會將數組中指定的js引入到html文件中,此外,如果你需要引入多個JS文件,僅有少數不想引入,還可以指定 excludeChunks 參數,它接受一個數組。

//webpack.config.js
module.exports = {
    //...
    plugins: [
        new HtmlWebpackPlugin({
            template: './public/index.html',
            filename: 'index.html', //打包後的文件名
            chunks: ['index']
        }),
        new HtmlWebpackPlugin({
            template: './public/login.html',
            filename: 'login.html', //打包後的文件名
            chunks: ['login']
        }),
    ]
}

執行 npm run build,可以看到 index.html 中僅引入了 indexJS 文件,而 login.html 中也僅引入了 loginJS 文件,符合我們的預期。

7.resolve 配置

resolve 配置 webpack 如何尋找模塊所對應的文件。webpack 內置 JavaScript 模塊化語法解析功能,默認會採用模塊化標準里約定好的規則去尋找,但你可以根據自己的需要修改默認的規則。

  1. modules

resolve.modules 配置 webpack 去哪些目錄下尋找第三方模塊,默認情況下,只會去 node_modules 下尋找,如果你我們項目中某個文件夾下的模塊經常被導入,不希望寫很長的路徑,那麼就可以通過配置 resolve.modules 來簡化。

//webpack.config.js
module.exports = {
    //....
    resolve: {
        modules: ['./src/components', 'node_modules'] //從左到右依次查找
    }
}

這樣配置之後,我們 import Dialog from 'dialog',會去尋找 ./src/components/dialog,不再需要使用相對路徑導入。如果在 ./src/components 下找不到的話,就會到 node_modules 下尋找。

      2. alias

resolve.alias 配置項通過別名把原導入路徑映射成一個新的導入路徑,例如:

//webpack.config.js
module.exports = {
    //....
    resolve: {
        alias: {
            'react-native': '@my/react-native-web' //這個包名是我隨便寫的哈
        }
    }
}

例如,我們有一個依賴 @my/react-native-web 可以實現 react-nativeweb。我們代碼一般下面這樣:

import { View, ListView, StyleSheet, Animated } from 'react-native';

配置了別名之後,在轉 web 時,會從 @my/react-native-web 尋找對應的依賴。

當然啦,如果某個依賴的名字太長了,你也可以給它配置一個短一點的別名,這樣用起來比較爽,尤其是帶有 scope 的包。

        3. extensions

適配多端的項目中,可能會出現 .web.js, .wx.js,例如在轉web的項目中,我們希望首先找 .web.js,如果沒有,再找 .js。我們可以這樣配置:

//webpack.config.js
module.exports = {
    //....
    resolve: {
        extensions: ['web.js', '.js'] //當然,你還可以配置 .json, .css
    }
}

首先尋找 ../dialog.web.js ,如果不存在的話,再尋找 ../dialog.js。這在適配多端的代碼中非常有用,否則,你就需要根據不同的平臺去引入文件(以犧牲了速度爲代價)。

import dialog from '../dialog';

當然,配置 extensions,我們就可以缺省文件後綴,在導入語句沒帶文件後綴時,會自動帶上extensions 中配置的後綴後,去嘗試訪問文件是否存在,因此要將高頻的後綴放在前面,並且數組不要太長,減少嘗試次數。如果沒有配置 extensions,默認只會找對對應的js文件。

       4. enforceExtension

如果配置了 resolve.enforceExtensiontrue,那麼導入語句不能缺省文件後綴。

       5. mainFields

有一些第三方模塊會提供多份代碼,例如 bootstrap,可以查看 bootstrappackage.json 文件:

{
    "style": "dist/css/bootstrap.css",
    "sass": "scss/bootstrap.scss",
    "main": "dist/js/bootstrap",
}

resolve.mainFields 默認配置是 ['browser', 'main'],即首先找對應依賴 package.json 中的 brower 字段,如果沒有,找 main 字段。

如:import 'bootstrap' 默認情況下,找得是對應的依賴的 package.jsonmain 字段指定的文件,即 dist/js/bootstrap

假設我們希望,import 'bootsrap' 默認去找 css 文件的話,可以配置 resolve.mainFields 爲:

//webpack.config.js
module.exports = {
    //....
    resolve: {
        mainFields: ['style', 'main'] 
    }
}

8.區分不同的環境

目前爲止我們 webpack 的配置,都定義在了 webpack.config.js 中,對於需要區分是開發環境還是生產環境的情況,我們根據 process.env.NODE_ENV 去進行了區分配置,但是配置文件中如果有多處需要區分環境的配置,這種顯然不是一個好辦法。

更好的做法是創建多個配置文件,如: webpack.base.jswebpack.dev.jswebpack.prod.js

  • webpack.base.js 定義公共的配置
  • webpack.dev.js:定義開發環境的配置
  • webpack.prod.js:定義生產環境的配置

webpack-merge 專爲 webpack 設計,提供了一個 merge 函數,用於連接數組,合併對象。

npm install webpack-merge -D
const merge = require('webpack-merge');
merge({
    devtool: 'cheap-module-eval-source-map',
    module: {
        rules: [
            {a: 1}
        ]
    },
    plugins: [1,2,3]
}, {
    devtool: 'none',
    mode: "production",
    module: {
        rules: [
            {a: 2},
            {b: 1}
        ]
    },
    plugins: [4,5,6],
});
//合併後的結果爲
{
    devtool: 'none',
    mode: "production",
    module: {
        rules: [
            {a: 1},
            {a: 2},
            {b: 1}
        ]
    },
    plugins: [1,2,3,4,5,6]
}

webpack.config.base.js 中是通用的 webpack 配置,以 webpack.config.dev.js 爲例,如下:

//webpack.config.dev.js
const merge = require('webpack-merge');
const baseWebpackConfig = require('./webpack.config.base');

module.exports = merge(baseWebpackConfig, {
    mode: 'development'
    //...其它的一些配置
});

然後修改我們的 package.json,指定對應的 config 文件:

//package.json
{
    "scripts": {
        "dev": "cross-env NODE_ENV=development webpack-dev-server --config=webpack.config.dev.js",
        "build": "cross-env NODE_ENV=production webpack --config=webpack.config.prod.js"
    },
}

你可以使用 merge 合併,也可以使用 merge.smart 合併,merge.smart 在合併loader時,會將同一匹配規則的進行合併,webpack-merge 的說明文檔中給出了詳細的示例。

9.定義環境變量

很多時候,我們在開發環境中會使用預發環境或者是本地的域名,生產環境中使用線上域名,我們可以在 webpack 定義環境變量,然後在代碼中使用。

使用 webpack 內置插件 DefinePlugin 來定義環境變量。

DefinePlugin 中的每個鍵,是一個標識符.

  • 如果 value 是一個字符串,會被當做 code 片段
  • 如果 value 不是一個字符串,會被stringify
  • 如果 value 是一個對象,正常對象定義即可
  • 如果 key 中有 typeof,它只針對 typeof 調用定義
//webpack.config.dev.js
const webpack = require('webpack');
module.exports = {
    plugins: [
        new webpack.DefinePlugin({
            DEV: JSON.stringify('dev'), //字符串
            FLAG: 'true' //FLAG 是個布爾類型
        })
    ]
}
//index.js
if(DEV === 'dev') {
    //開發環境
}else {
    //生產環境
}

 

 

10.利用webpack解決跨域問題

假設前端在3000端口,服務端在4000端口,我們通過 webpack 配置的方式去實現跨域。

首先,我們在本地創建一個 server.js

let express = require('express');

let app = express();

app.get('/api/user', (req, res) => {
    res.json({name: '劉小夕'});
});

app.listen(4000);

執行代碼(run code),現在我們可以在瀏覽器中訪問到此接口: http://localhost:4000/api/user

index.js 中請求 /api/user,修改 index.js 如下:

//需要將 localhost:3000 轉發到 localhost:4000(服務端) 端口
fetch("/api/user")
    .then(response => response.json())
    .then(data => console.log(data))
    .catch(err => console.log(err));

我們希望通過配置代理的方式,去訪問 4000 的接口。

配置代理

修改 webpack 配置:

//webpack.config.js
module.exports = {
    //...
    devServer: {
        proxy: {
            "/api": "http://localhost:4000"
        }
    }
}

重新執行 npm run dev,可以看到控制檯打印出來了 {name: "劉小夕"},實現了跨域。

大多情況,後端提供的接口並不包含 /api,即:/user/info/list 等,配置代理時,我們不可能羅列出每一個api。

修改我們的服務端代碼,並重新執行。

//server.js
let express = require('express');

let app = express();

app.get('/user', (req, res) => {
    res.json({name: '劉小夕'});
});

app.listen(4000);

儘管後端的接口並不包含 /api,我們在請求後端接口時,仍然以 /api 開頭,在配置代理時,去掉 /api,修改配置:

//webpack.config.js
module.exports = {
    //...
    devServer: {
        proxy: {
            '/api': {
                target: 'http://localhost:4000',
                pathRewrite: {
                    '/api': ''
                }
            }
        }
    }
}

重新執行 npm run dev,在瀏覽器中訪問: http://localhost:3000/,控制檯中也打印出了{name: "劉小夕"},跨域成功,

11.前端模擬數據

簡單數據模擬

module.exports = {
    devServer: {
        before(app) {
            app.get('/user', (req, res) => {
                res.json({name: '劉小夕'})
            })
        }
    }
}

src/index.js 中直接請求 /user 接口。

fetch("user")
    .then(response => response.json())
    .then(data => console.log(data))
    .catch(err => console.log(err));

使用 mocker-api mock數據接口

mocker-api 爲 REST API 創建模擬 API。在沒有實際 REST API 服務器的情況下測試應用程序時,它會很有用。

  1. 安裝 mocker-api:
npm install mocker-api -D

     2. 在項目中新建mock文件夾,新建 mocker.js.文件,文件如下:

module.exports = {
    'GET /user': {name: '劉小夕'},
    'POST /login/account': (req, res) => {
        const { password, username } = req.body
        if (password === '888888' && username === 'admin') {
            return res.send({
                status: 'ok',
                code: 0,
                token: 'sdfsdfsdfdsf',
                data: { id: 1, name: '劉小夕' }
            })
        } else {
            return res.send({ status: 'error', code: 403 })
        }
    }
}

         3. 修改 webpack.config.base.js:

const apiMocker = require('mocker-api');
module.export = {
    //...
    devServer: {
        before(app){
            apiMocker(app, path.resolve('./mock/mocker.js'))
        }
    }
}

這樣,我們就可以直接在代碼中像請求後端接口一樣對mock數據進行請求。

      4. 重啓 npm run dev,可以看到,控制檯成功打印出來 {name: '劉小夕'}

      5. 我們再修改下 src/index.js,檢查下POST接口是否成功

//src/index.js
fetch("/login/account", {
    method: "POST",
    headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
    },
    body: JSON.stringify({
        username: "admin",
        password: "888888"
    })
})
    .then(response => response.json())
    .then(data => console.log(data))
    .catch(err => console.log(err));

可以在控制檯中看到接口返回的成功的數據。

進階篇就到這裏結束啦,最後一篇是優化篇,下週一帶上小板凳和瓜子來約。

 

 

 

轉載自:https://juejin.im/post/5e6518946fb9a07c820fbaaf#heading-7

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章