react开发环境搭建

一.npm init 初始化环境创建package.json

二.安装wepack

npm install --D webpack webpack-dev-server webpack-cli
webpack4.x要求安装webpack-cli
webpack-dev-server是一个基于Express框架的Node.js服务器。它还提供了一个客户端的运行环境,会被注入到页面代码中执行,并通过Socket.IO与服务器通信。
服务器端的每次改动与重新构建都会被通知到页面上。还提供了如模块替换这样强大的功能。
复制代码

三.webpack基本配置

1.项目根目录新建build文件夹,创建webpack.config.js
const path = require("path");

function resolve(dir) {
    return path.resolve(__dirname, dir)
}

module.exports = {
    // 指定构建环境  
    mode:"development",
    // 入口
    entry: {
        app: "./src/index" 
    },
    // 出口
    output: {
        path : resolve("../dist"),
        filename: "js/[name].[hash].js",
        publicPath: "/" // 打包后的资源的访问路径前缀
    },
    // 模块
    module:{

    },
    // 插件
    plugins:[

    ],
    // 开发环境本地启动的服务配置
    devServer: {

    }
}
复制代码
2.编写,配置html模板,实现html模板的打包,安装插件
npm install -D html-webpack-plugin
在根目录下新建index.html

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0">
  <title>mydemo</title>
</head>

<body>
  <div id="app"></div>
  <!-- built files will be auto injected -->
</body>

</html>
复制代码
3.为了区分开发环境和生产环境,下面我们一步一步抽取wenpack公共配置

分别创建 utils.js ,webpack.base.config.js , webpack.dev.config.js , webpack.prod.config.js

四.babel配置

npm install -D @babel/core @babel/preset-env @babel/preset-react 
npm install -D @babel/plugin-transform-runtime @babel/runtime @babel/runtime-corejs2
复制代码
  • ==@babel/core== babelbabel的核心库

  • ==@babel/preset-env== 把es6,es7语法转换成es5。bebel7以上的版本只用这一个预设包就可以实现语法的转换,已经废弃了preset-stage-0,preset-stage-1,preset-stage-2等这些包。但是这个包还不能转换es6,es7的一些新特性比如Array.includes(),这就需要我们使用@babel/plugin-transform-runtime了

  • ==@babel/preset-react== 把react语法转换为es5

  • ==@babel/plugin-transform-runtime== 支持一些es6,es7的新语法

那么安装完了,我们需要添加babel的配置了,在项目目录创建.babelrc,配置内容如下

{
  "presets": [
    ["@babel/preset-env", {
      "modules": false,
      "targets": {
        "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
      }
    }],
    "@babel/preset-react"
  ],
  "plugins": [
    ["@babel/plugin-transform-runtime",{
      "corejs": 2, // polyfill 需要使用@babel/runtime-corejs2
      "useBuildIns":"usage", //按需引入,即使用什么新特性打包什么新特性, 可以减小打包的体积
    }]
    
  ]
}
复制代码

五.loader配置

  • 安装babel-loader
npm install -D babel-loader
复制代码
  • style-loader,css-loader编译css文件
npm install -D style-loader css-loader 
复制代码
  • url-loader file-loader引入文件路径(图片,字体)
npm install -D url-loader file-loader
复制代码
  • less-loader
npm install -D less less-loader
复制代码

安装完这些包之后,我们需要在webpacl.base.config.js添加打包编译构建规则
在module下添加rules属性

  • postcss-loader + autoprefixer
npm install postcss-loader --save-dev
npm install autoprefixer --save-dev
复制代码

    rules: [
      {
        test: /\.(js|jsx)$/,//一个匹配loaders所处理的文件的拓展名的正则表达式,这里用来匹配js和jsx文件(必须)
        exclude: /node_modules/,//屏蔽不需要处理的文件(文件夹)(可选)
        loader: 'babel-loader',//loader的名称(必须)
      },
      {
        test: /\.css$/,
        use: [
          {
            loader: devMode ? 'style-loader' : MiniCssExtractPlugin.loader, // 创建 <style></style>
          },
          {
            loader: 'css-loader',  // 转换css
          },
          'postcss-loader'
        ]
      },
      {
        test: /\.less$/,
        use: [
          {
          // 开发环境不要MiniCssExtractPlugin,因为它不会热更新
            loader: devMode ? 'style-loader' : MiniCssExtractPlugin.loader,
          },
          {
            loader: 'css-loader',
          },
          'postcss-loader',
          {
            loader: 'less-loader', // 编译 Less -> CSS
          },
        ],
      },
      {
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
        loader: 'url-loader',
        include: [resolve('static'), resolve('src')],
        options: {
          limit: 10000, // url-loader 包含file-loader,这里不用file-loader, 小于10000B的图片base64的方式引入,大于10000B的图片以路径的方式导入
          name: 'static/img/[name].[hash:7].[ext]'
        }
      },
      {
        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
        include: [resolve('static'), resolve('src')],
        loader: 'url-loader',
        options: {
          limit: 10000, // 小于10000B的图片base64的方式引入,大于10000B的图片以路径的方式导入
          name: 'static/fonts/[name].[hash:7].[ext]'
        }
      }
    ]
但我们的项目中有的图片列表是用v-for遍历出来的,也就是url放到了js中(vue文件的data里),
这样就不能被base64编码了,url-loader只会去编译html以及css中的image。
所以可以使用import图片的方式通过一个变量去接受,然后将这些变量放到v-for中去渲染。
复制代码

npm run build 后查看dist应用

npm install -g http-server
安装成功之后,cd dist目录,执行http-server命令
http-server -p 443 指定端口
复制代码

六.webpack react配置

  1. 引入安装react
npm install -S react react-dom
复制代码

2.react-router4.x

npm install -S react-router-dom
复制代码
npm install -D copy-webpack-plugin
复制代码

七.anted按需引入

npm install antd --save
npm install babel-plugin-import --save-dev
复制代码

高版本的antd官方把图标库也构建到release包,所以导致打包变得很大,仅仅icon图标库就有几百KB,请看下图。

八、打包优化

  • react路由的异步加载
  • css处理
    • 使用mini-css-extract-plugin把css从bundle包中抽取
    • 使用optimize-css-assets-webpack-plugin压缩css代码
    • 使用postcss-loader,autoprefixer对浏览器兼容性的css代码加前缀
  • js的处理
    • 使用uglifyjs-webpack-plugin代码压缩
    • 多线程打包:happypack
    • 拆包,js的bundle包的提取(拆包)
1.分析打包的文件大小原因
npm install -D clean-webpack-plugin webpack-bundle-analyzer
clean-webpack-plugin 在打包的时候会删除之前的打包目录
webpack-bundle-analyzer 在打包结束的时候,会启动启动一个服务在浏览器查看打包的大小和包含的内容等
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const { BundleAnalyzerPlugin } = require("webpack-bundle-analyzer");
插件的引用已经改了

复制代码
2.异步加载

首先是 code splitting(代码分割)
如果你不太熟悉这个功能,webpack 基本上可以帮助你把代码打包成多个chunk,当用户打开你的应用的时候,先会下载一个主bundle,然后当用户导航到一些页面包含了其他的逻辑和静态资源的使用,再按需加载这些chunk。但是要手动处理成这个效果非常的复杂,当然这样处理后可以很有效地减少用户的白屏时间,并且让移动端用户有更好的体验。webpack(或者其他解决方案)在这里扮演了一个很重要的角色,他可以在创建这些bundle的时候处理这些复杂的逻辑,并且在需要的时候再去下载他们。所以我们所需要做的就是将该功能合并到我们的应用程序中,这样用户就可以获得无缝的体验。

import React, { Suspense } from "react";
import { HashRouter as Router, Switch, Link, Route } from 'react-router-dom';

const HomeComponent = React.lazy(() => import(/* webpackChunkName: "HomeComponent" */ '../views/home'));
const ListComponent = React.lazy(() => import(/* webpackChunkName: "ListComponent" */ '../views/list'));
const Home = (props) => {
  return (
    <Suspense fallback={<div>加载中...</div>}>
      <HomeComponent {...props} />
    </Suspense>
  )
}
const List = (props) => {
  return (
    <Suspense fallback={<div>加载中...</div>}>
      <ListComponent {...props} />
    </Suspense>
  )
}
class AppRouter extends React.Component {
  render() {
    return (
      <Router>
        <div>
          <ul>
            <li><Link to="/home">home</Link></li>
            <li><Link to="/list">blog</Link></li>
          </ul>
          {/* Switch只显示一个组件。加exact表示精确匹配/。如果不加exact,/xxx也会匹配/。  */}
          <Switch>
            {/* exact */}
            <Route path="/home" component={Home} />
            <Route exact path="/list" component={List} />
          </Switch>
        </div>
      </Router>
    )
  }
}
export default AppRouter;

复制代码
3.css处理
1.npm install --save-dev mini-css-extract-plugin
webpack4需要自己使用压缩器,可以使用 optimize-css-assets-webpack-plugin 插件。 设置 optimization.minimizer 覆盖webpack默认提供的,确保也指定一个JS压缩器

MiniCssExtractPlugin 失效打包后还是在一起
经过排查const devMode = process.env.NODE_ENV !== 'production'; 这里的变量出来时undefined
所以我们要在package.json 里面配上 NODE_ENV=production
复制代码

因为uglifyjs不支持es6语法,所以用terser-webpack-plugin替代uglifyjs-webpack-plugin
terser-webpack-plugin安装:yarn add terser-webpack-plugin -D
使用: webpack.config.js

  minimizer: [new TerserJSPlugin({
        cache: true, // 是否缓存
        paraller: true, // 是否并行打包
        sourceMap: true
    })],
复制代码
4.js处理

多线程打包:happypack

npm install happypack --save-dev
npm install os --save-dev

const HappyPack = require('happypack');
const os = require('os');
const happyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length });

  {
    test: /\.(js|jsx)$/, // 一个匹配loaders所处理的文件的拓展名的正则表达式,这里用来匹配js和jsx文件(必须)
    exclude: /node_modules/, // 屏蔽不需要处理的文件(文件夹)(可选)
    use: [
      {
        loader: 'happypack/loader?id=babelLoader'
      }
    ]
  },

new happypack({
  id: 'babelLoader',
  use: [{
    loader: 'babel-loader'
  }],
  //共享进程池
  threadPool: happyThreadPool,
}),
复制代码

九、开发插件及开发规范

1.axios
npm install axios
复制代码
2.rematch
npm install @rematch/core --save
复制代码

十、问题

1.最近在安装使用webpack的copy-webpack-plugin 拷贝插件的时候,报了一些错误:
错误详见下面代码,没有粘贴完, 大概意思就是Copy Plugin的初始化对象不正确,查看了官网也没有看出所以然,最后在npm官网上找打了原因


    new CopyWebpackPlugin([
      {
        patterns: [
          {
            from: resolve('/static'),
            to: 'static'
          }
        ]
      }
    ])
但是和htmlplugin会有冲突  所以下载低版本的copy-webpack-plugin插件就好了
复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享