react项目打包和优化

项目打包和优化-项目打包

目标:能够通过命令对项目进行打包 步骤

  1. 在项目根目录打开终端,输入打包命令:npm run build
  2. 等待打包完成,打包后的内容被放在项目根下的 build 文件夹中

项目打包和优化-项目本地预览

目标:能够在本地预览打包后的项目 步骤

  1. 全局安装本地服务包:npm i -g serve,该包提供了 serve 命令,用来启动本地服务
  2. 在项目根目录中执行命令:serve -s ./build,在 build 目录中开启服务器
  3. 在浏览器中访问:http://localhost:5000/ 预览项目

项目打包和优化-打包体积分析

目标:能够分析项目打包体积

分析说明:通过分析打包体积,才能知道项目中的哪部分内容体积过大,才能知道如何来优化

步骤

  1. 安装分析打包体积的包:npm i source-map-explorer

  2. 在 package.json 中的 scripts 标签中,添加分析打包体积的命令

    "scripts": {
      "analyze": "source-map-explorer 'build/static/js/*.js'",
    }
    复制代码
  3. 对项目打包:npm run build(如果已经打过包,可省略这一步)

  4. 运行分析命令:npm run analyze

  5. 通过浏览器打开的页面,分析图表中的包体积

核心代码

项目打包和优化-生产环境优化

目标:能够根据是否为生产环境对redux中间件进行优化 核心代码

store/index.js 中:

let middlewares
​
if (process.env.NODE_ENV === 'production') {
  // 生产环境,只启用 thunk 中间件
  middlewares = applyMiddleware(thunk)
} else {
  middlewares = composeWithDevTools(applyMiddleware(thunk))
}
复制代码

项目打包和优化-路由懒加载

目标:能够对路由进行懒加载实现代码分隔 步骤

  1. 在 App 组件中,导入 Suspense 组件
  2. 在 Router 内部,使用 Suspense 组件包裹组件内容
  3. 为 Suspense 组件提供 fallback 属性,指定 loading 占位内容
  4. 导入 lazy 函数,并修改为懒加载方式导入路由组件

核心代码

App.js 中:

import { lazy, Suspense } from 'react'
​
// 导入页面组件
const Login = lazy(() => import('./pages/Login'))
const Layout = lazy(() => import('./pages/Layout'))
​
const App = () => {
  return (
    <Router history={history}>
      <Suspense
        fallback={
          <div
            style={{
              textAlign: 'center',
              marginTop: 200
            }}
          >
            loading...
          </div>
        }
      >
        <div className="app">
          <Route exact path="/" render={() => <Redirect to="/home" />}></Route>
          <Route path="/login" component={Login}></Route>
          <AuthRoute path="/home" component={Layout}></AuthRoute>
        </div>
      </Suspense>
    </Router>
  )
}
​
export default App
复制代码

pages/Layout/index.js 中:

// 使用 lazy 导入组件
const Home = lazy(() => import('../Home'))
const Article = lazy(() => import('../Article'))
const Publish = lazy(() => import('../Publish'))
​
// ...
复制代码

项目打包和优化-去掉console

npm i [email protected]

const TerserPlugin = require('terser-webpack-plugin')
​
module.exports = {
  webpack: {
    // 省略其他...
        plugins: [
      new TerserPlugin({
        terserOptions: {
          compress: {
            drop_console: process.env.NODE_ENV === 'production' 
            // 生产环境下移除控制台所有的内容
          }
        }
      })
    ]
  }
}
复制代码

项目打包和优化-配置CDN

目标:能够对第三方包使用CDN优化

分析说明:通过 craco 来修改 webpack 配置,从而实现 CDN 优化

github.com/facebook/cr…

核心代码

craco.config.js 中:

const path = require('path')
// HtmlWebpackPlugin
const { whenProd, getPlugin, pluginByName } = require('@craco/craco')
module.exports = {
  webpack: {
    alias: {
      '@': path.join(__dirname, 'src')
    },
    configure: (webpackConfig) => {
      let cdn = {
        js: [],
        css: []
      }
      // 对webpack进行配置
      whenProd(() => {
        // 只会在生产环境执行
        webpackConfig.externals = {
          react: 'React',
          'react-dom': 'ReactDOM',
          redux: 'Redux',
          
        }
​
        cdn = {
          js: [
            'https://cdn.bootcdn.net/ajax/libs/react/17.0.2/umd/react.production.min.js',
            'https://cdn.bootcdn.net/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js',
            'https://cdn.bootcdn.net/ajax/libs/redux/4.1.0/redux.min.js'
          ],
          css: []
        }
      })
​
      const { isFound, match } = getPlugin(
        webpackConfig,
        pluginByName('HtmlWebpackPlugin')
      )
      if (isFound) {
        // 找到了html的插件
        match.options.cdn = cdn
      }
​
      return webpackConfig
    }
  }
}
​
复制代码

public/index.html 中:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta
      name="description"
      content="Web site created using create-react-app"
    />
    <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
    <!--
      manifest.json provides metadata used when your web app is installed on a
      user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
    -->
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <!--
      Notice the use of %PUBLIC_URL% in the tags above.
      It will be replaced with the URL of the `public` folder during the build.
      Only files inside the `public` folder can be referenced from the HTML.

      Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
      work correctly both with client-side routing and a non-root public URL.
      Learn how to configure a non-root public URL by running `npm run build`.
    -->
    <title>React App</title>
    <% htmlWebpackPlugin.options.cdn.css.forEach(cdnURL => { %>
      <link rel="stylesheet" href="<%= cdnURL %>"></link>
    <% }) %>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
    <!--
      This HTML file is a template.
      If you open it directly in the browser, you will see an empty page.

      You can add webfonts, meta tags, or analytics to this file.
      The build step will place the bundled scripts into the <body> tag.

      To begin the development, run `npm start` or `yarn start`.
      To create a production bundle, use `npm run build` or `yarn build`.
    -->
    <% htmlWebpackPlugin.options.cdn.js.forEach(cdnURL => { %>
      <script src="<%= cdnURL %>"></script>
    <% }) %>
  </body>
</html>

复制代码

猜你喜欢

转载自juejin.im/post/7032993931017240606