使用webpack5搭建可用的react开发环境

开始

前言:webpack从入行到现在,一直都有使用,期间也断断续续的学了一些东西,文章计划记录一下自己从学习的一些东西,正好最近webpack5更新了,研究下新东西,持续更新查漏补缺吧

本文章采用版本号:5.65.0

初始化项目

1、创建文件夹,初始化npm、安装webpack

npm init // 一路enter到底
npm i webpack webpack-cli -D
复制代码

2、创建项目入口文件src/index.js,这里我们写上一个console

console.log('hello')
复制代码

初始化配置

1、创建webpack配置文件,设置entry(入口)、output(出口)

我们直接在当前目录下创建webpack.config.js

const path = require('path')

module.exports = {
    entry: {
        index: path.resolve(__dirname, 'src/index.js')
    },
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: '[name].js',
        clean: true //每次打包前清空目录
    }
}
复制代码

老版本中clean是使用 clean-webpack-plugin 插件

2、添加构建命令,在package.json中的script添加build命令

"scripts": {
    "build": "webpack --config webpack.config.js"
},
复制代码

3、运行npm run build,如果不出意外的话,会生成dist/index.js文件,这时候我们只需要引用这个文件就ok了

html-webpack-plugin

上面执行完之后我们可能还需要一个html去引用这个js、我们可以在dist目录下手写一个index.html,但是我们开启了clean,每次打包都要手写肯定不合适,这时候我们可以用一个插件解决html-webpack-plugin

1、安装html-webpack-plugin

npm i html-webpack-plugin -D
复制代码

2、在package.json中添加plugins配置

plugins: [
    new HtmlWebpackPlugin({
        template: path.resolve(__dirname, './index.html'),
        filename: 'index.html'
    })
]
复制代码

3、再次运行npm run build

我们可以看到build之后dist目录下自带了index.html,而且html中还自动引入了index.js,甚至还贴心的加上defer,如果考虑兼容性不想要可以添加配置

scriptLoading: 'blocking'
复制代码

更多配置

开发模式

现在我们能进行很简单的打包了,但是还有很多工作没做,比如我们每次改了文件,想看到效果都需要重新打包一次代码,这对开发来说很不友好,所以我们需要一个开发模式,常见的有两种,watch和devServer

watch

该模式如同名字一样,就是监听文件更改自动打包,配置也很简单,我们只需要在增加一条命令即可

"watch": "webpack --config webpack.config.js --watch"
复制代码

然后我们运行npm run watch 可以看到当前进程并没有终止,尝试更改index.js,有重新执行打包,index.js内容也变更

devServer

该模式就是在本地启动一个服务,该服务可进行监听改变、自动刷新等操作

1、安装 webpack-dev-server

npm i webpack-dev-server -D
复制代码

2、webpack.config.js增加配置

devServer: {
    port: 3000, // 端口
    open: true, // 自动打开
    compress: true, //启用gzip压缩
    client: {
        progress: true // 浏览器打印进度
    }
}
复制代码

3、package.json添加命令

"dev": "webpack serve --config webpack.config.js"
复制代码

完成之后我们执行npm run dev,执行完之后浏览器会自动打开localhost:3000页面,更改index.js也会自动刷新

支持React

现在我们需要为我们的项目增加React的支持

安装babel

npm i @babel/core -D // babel核心
npm i @babel/preset-env -D // 转义js语法、promise、async等
npm i @babel/preset-react -D // 转移react相关语法(jsx)
npm i babel-loader -D //loader
复制代码

配置loader

1、添加webpack配置,是的babel处理我们的js和jsx文件

module: {
    rules: [
        {
            test: /(\.jsx|\.js)$/,
            use: ["babel-loader"],
            exclude: /node_modules/ // 排除node_modules文件
        }
    ],
}
复制代码

2、添加babel配置、在项目下新增babel.config.js文件,增加如下配置

{
    "presets": [
        [
            "@babel/preset-env",
            {
                "useBuiltIns": "usage",
                "corejs": 3
            }
        ],
        "@babel/preset-react"
    ]
}
复制代码

3、增加.browserslistrc文件配置browserslist

> 1%
last 2 versions
not ie <= 8
复制代码

4、测试代码

index.js

import {render} from 'react-dom'
import React from 'react'
import App from './App';

render(<App />, document.getElementById('root'))
复制代码

App.js

import React from 'react'

const App = () => {
    return <div>Hello React</div>
}

export default App
复制代码

然后运行npm run dev 可以正常运行了

处理异常

这里运行起来你可能可以看到一个警告

asset size limit: The following asset(s) exceed the recommended size limit (244 KiB). This can impact web performance.
复制代码

这是由于单个文件大小超出webpack 性能项配置的大小,性能优化后面讲解,这里可以在webpack加下面配置直接跳过

performance: {
    hints: false 
},
复制代码

处理CSS

处理css文件 css-loader style-loader

1、安装依赖

npm i css-loader -D // 处理css文件
npm i style-loader -D // 处理后使用style插入html中
复制代码

2、在rules下面添加配置

{
    test: /\.css$/,
    use:["style-loader","css-loader"],
    exclude: /node_modules/
},
复制代码

现在我们引入一个css文件就可以看到我们打包的页面中带了一个style

image.png

处理scss文件 sass-loader sass

1、安装依赖

npm i sass -D // sass核心
npm i sass-loader -D // loader
复制代码

2、在rules下面添加配置

{
    test: /\.s(a|c)ss$/,
    use:["style-loader","css-loader","sass-loader"],
    exclude: /node_modules/
}
复制代码

分离css文件

现在我们的配置是将css打入js中,然后js执行时候使用style标签插入,这会严重增加js的包大小、在生产环境我们通常是分离css和js文件,这就需要使用到一个webpack插件mini-css-extract-plugin,在开发环境我们依然可以使用style-loader,因为这相比mini-css-extract-plugin要更快

1、安装

npm i mini-css-extract-plugin -D
复制代码

2、使用

...
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const IS_DEV = process.env.NODE_ENV === 'development'
...

// 修改刚才针对scss和css文件的处理

{
    test: /\.css$/,
    use: [IS_DEV ? "style-loader" : MiniCssExtractPlugin.loader, "css-loader"],
    exclude: /node_modules/
},
{
    test: /\.s(a|c)ss$/,
    use: [IS_DEV ? "style-loader" : MiniCssExtractPlugin.loader, "css-loader", "sass-loader"],
    exclude: /node_modules/
}

// 在plugins中添加
new MiniCssExtractPlugin({
    filename: '[name].[hash].css' // 生成hash名称
}),
复制代码

CSSModule

只需要在css-loader中开启modules就ok,配置如下

{
    test: /\.s(a|c)ss$/,
    use: [
        IS_DEV ? "style-loader" : MiniCssExtractPlugin.loader,
        {
            loader: "css-loader",
            options: {
                modules: {
                    localIdentName: '[local]--[hash:base64:5]'
                },
            }
        },
        "sass-loader"
    ],
    exclude: /node_modules/
}
复制代码

使用postcss 自动添加厂商前缀

作用:自动各浏览器厂商前缀

1、安装

npm i postcss -D
npm i postcss-loader -D
npm i postcss-preset-env -D
复制代码

2、配置

在webpack中处理css位置添加postcss-loader,添加后

{
    test: /\.s(a|c)ss$/,
    use: [
        IS_DEV ? "style-loader" : MiniCssExtractPlugin.loader,
        {
            loader: "css-loader",
            options: {
                modules: {
                    localIdentName: '[local]--[hash:base64:5]'
                },
                sourceMap: IS_DEV
            }
        },
        "postcss-loader",
        "sass-loader"
    ],
    exclude: /node_modules/
}
复制代码

然后根目录新建个配置文件postcss.config.js

module.exports = {
    plugins: [
        ['postcss-preset-env']
    ]
}
复制代码

处理文件 asset 取代 file-loaderurl-loader

在webpack5以前,咱们处理图片资源文件一般是 file-loader 结合 url-loader,小文件base64打入js中,大文件输出文件,webpack5直接自带了处理文件的功能assetModule,配置起来相对简单一些

{
    test: /\.(png|svg|jpg|jpeg|gif)$/i,
    type: 'asset',
    parser: {
        dataUrlCondition: {
            maxSize: 1 * 1024 // 1kb以下小文件打入js中
        }
    },
    generator: {
        filename: 'static/[hash][ext][query]'
    }
}
复制代码

区分环境

我们在开发中通常会有两个环境、开发环境和生产环境,webpack给我们提供了mode进行配置区分,而在打包配置中针对不同环境同一个loader可能配置不一样,这使得我们需要两份不同的配置文件

1、首先我们安装所需要的依赖

npm i webpack-merge -D // 合并配置文件
npm i cross-env -D // process.env兼容多环境
复制代码

2、 新建一个build目录,用于放置打包配置,新建以下文件

  • webpack.development.js 开发环境配置
module.exports = {
    mode: 'development',
    performance: {
        hints: false 
    },
    devServer: {
        port: 3000, // 端口
        open: true, // 自动打开
        compress: true, //启用gzip压缩
        client: {
            progress: true // 浏览器打印进度
        }
    }
}
复制代码
  • webpack.production.js 开发环境配置
module.exports = {
    mode: "production"
}
复制代码
  • webpack.common.js 公共配置,dev和prod环境都会用到的配置
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    entry: {
        index: path.resolve(__dirname, '../src/index.js')
    },
    output: {
        path: path.resolve(__dirname, '../dist'),
        filename: '[name].js',
        clean: true
    },
    module: {
        rules: [
            {
                test: /(\.jsx|\.js)$/,
                use: ["babel-loader"],
                exclude: /node_modules/
            }
        ],
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: path.resolve(__dirname, '../index.html'),
            filename: 'index.html',
            scriptLoading: 'blocking'
        })
    ]
}
复制代码
  • webpack.config.js 根据环境使用不同的配置
const merge = require('webpack-merge').default;
const commonConfig = require('./webpack.common');
const devConfig = require('./webpack.development');
const proConfig = require('./webpack.production');

module.exports = () => {
    if(process.env.NODE_ENV === 'development') {
        return merge(commonConfig, devConfig, {mode: 'development'})
    }
    return merge(commonConfig, proConfig, {mode: 'production'})
}
复制代码

3、修改命令

"build": "cross-env NODE_ENV=production webpack --config ./build/webpack.config.js",
"dev": "cross-env NODE_ENV=development webpack serve --config ./build/webpack.config.js"
复制代码

现在我们开发时运行npm run dev,上线运行npm run build打包即可

为什么使用 cross-env

这是因为设置环境变量时候不同系统命令不同

  • Windows
set NODE_ENV=development
复制代码
  • Max
export NODE_ENV=development
复制代码

cross-env能帮我们兼容不同的系统

结尾

现在这个已经能实现一个react项目的开发和打包,还有许多优化的地方,待后续再写吧

猜你喜欢

转载自juejin.im/post/7053188321022836772