webpack5

近期终于有时间和精力专注于公司技术基础建设了,于是一开始,将公司的Saas系统改造成了微前端模式,解决了历史遗留的一部分问题

接着,想着webpack5已经发布这么久了,该在生产环境用起来了,也顺势想推动微前端webpack5vite在业内的普及率,没看过我之前文章的朋友可以在文末找找,干货真的很多

正式开始

webpack5升级后,有哪些改变?

  • 通过持久化缓存提高性能

  • 采用更好的持久化缓存算法和默认行为

  • 通过优化 Tree Shaking 和代码生成来减小Bundle体积(干掉了nodejs的polyfill)

  • 提高 Web 平台的兼容性

  • 清除之前为了实现 Webpack4 没有不兼容性变更导致的不合理 state

  • 尝试现在引入重大更改来为将来的功能做准备,以使我们能够尽可能长时间地使用 Webpack 5

  • 新增Module Federation(联邦模块)

搭建指南

推荐大家使用我在我们公司(深圳明源云空间)做的脚手架,给大家一键生成项目模板,这样大家在看本文的时候会得到更好的提升

生成模板步骤:

npm  i ykj-cli -g
ykj init webpack5 (这里选择通用项目模板)
cd webpack5
yarn
yarn dev

开始搭建

  • 首先新建文件夹,使用yarn初始化项目

mkdir webpack5-demo
cd webpack5-demo
yarn init webpack5-demo
...一路回车
  • 下载webpack webpack-cli最新版本:

yarn add webpack@next webpack-cli@next -D
  • 然后安装React react-dom17版本的库

yarn add react@17.0.0 react-dom@17.0.0 --save
  • 接着安装react官方热更新推荐的库

yarn add react-refresh -D
  • 安装less css style标签 postcss等样式处理的库(mini-css-extract-plugin要安装@next版本的)

yarn add less less-loader css-loader style-loader mini-css-extract-plugin@next -D
  • 安装相关babel依赖

yarn add core-js@3.9.0 @babel/core@next  babel-loader@next @babel/preset-env@next -D

babel具体要哪些配置,建议大家参考我的模板里面


完成了依赖的准备工作,开始搭建项目

  • 项目根目录创建config文件夹,用于放置webpack配置文件

  • config文件夹下新建四个文件

paths.js//存放路径
webpack.base.js //基础配置
webpack.dev.js//开发配置
webpack.prod.js//生产配置
  • paths文件内,用变量记录几个关键目录:

const path = require('path');module.exports = {// 源码目录src: path.resolve(__dirname, '../src'),// 构建后的资源产物文件夹build: path.resolve(__dirname, '../dist'),// 静态资源public: path.resolve(__dirname, '../public'),
};
  • 编写基础webpack.base.js配置文件,引入依赖

//webpack.base.js
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');
const paths = require('./paths');
  • 编写entryoutput字段:

 entry: paths.src + 'index.tsx',output: {path: path.resolve(__dirname, '../dist'),filename: '[name].[contenthash].js',publicPath: '',},

这里要注意的是,webpack5contenthash算法进行了优化,这里可以在chunkhashcontenthash中选择一个,建议contenthash

  • 编写基础loader配置:

    module: {rules: [{use: 'babel-loader',test: /\.(ts|tsx)$/,exclude: /node_modules/,},{use: ['style-loader', 'css-loader', 'less-loader'],test: /\.(css|less)$/,},{type: 'asset',test: /\.(png|svg|jpg|jpeg|gif)$/i,},],},

这里要注意的是:webpack5对于资源,类似:图片、字体文件等,可以用内置的asset去处理,不用url-loaderfile-loader

  • 接着,由于项目需要配置别名和省略后缀名,我们先配置resolve字段(我是TypeScript+React技术栈):

 resolve: {extensions: ['.ts', '.tsx', '.js', '.json', '.jsx'],alias: {'@': paths.src,'@c': paths.src + '/components','@m': paths.src + '/model','@s': paths.src + '/services','@t': paths.src + '/types',},},
  • 插件的话,由于是基础配置,只要一个clean、html的插件即可

  plugins: [new CleanWebpackPlugin(),new HtmlWebpackPlugin({template: './public/index.html',}),],
  • 在项目根目录新建文件babel.config.js

const { argv } = require('yargs');
const isDev = argv.mode === 'development';
const plugins = [['const-enum',{transform: 'constObject',},],'lodash','@babel/plugin-transform-runtime',//支持import 懒加载'@babel/plugin-syntax-dynamic-import','@babel/plugin-transform-async-to-generator','transform-class-properties',['import',{libraryName: 'antd',libraryDirectory: 'es',style: true, // or 'css'},'antd',],['import',{libraryName: 'ykj-ui',libraryDirectory: 'lib/components',style: true, // or 'css'},'ykj-ui',],
];
module.exports = (api) => {api.cache(true);return {presets: [['@babel/preset-env',{corejs: 3.9,useBuiltIns: 'usage',},],['@babel/preset-react',{runtime: 'automatic',},],'@babel/preset-typescript',],plugins: isDev ? [...plugins, 'react-refresh/babel'] : [...plugins],};
};

这样,我们的基础webpack配置就好了,捋一捋先:

  • 用babel处理tsx tses高阶语法

  • loader处理less语法

  • 用插件处理了html和负责清理工作

  • resolve字段配置了别名和省略文件后缀

  • 用内置的asset处理了静态文件,例如图片等

编写webpack.dev.js开发配置

引入依赖

const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
const { HotModuleReplacementPlugin } = require('webpack');
const { merge } = require('webpack-merge');
const common = require('./webpack.base');

先引入了热更新、合并配置、基础配置、官方react热更新依赖

接着编写配置

const devConfig = {mode: 'development',devServer: {port: 3000,contentBase: '../dist',open: true,hot: true,},target: 'web',plugins: [new HotModuleReplacementPlugin(), new ReactRefreshWebpackPlugin()],devtool: 'eval-cheap-module-source-map',
};module.exports = merge(common, devConfig);

注意:这里要设置target: 'web'才会有热更新效果

  • devtool在开发模式最佳实践是:eval-cheap-module-source-map

这样,我们的开发模式配置就搭建好了,只要在public文件夹下编写一个index.html,就可以跟之前一样,开始写react项目了


开始编写webpack.prod.js生产配置

  • 引入依赖:

const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const { merge } = require('webpack-merge');
const common = require('./webpack.base');
  • 生产环境要抽离css标签,所以这里针对less和css要做特殊处理,一个是postcss处理样式兼容性问题,一个是MiniCssExtractPlugin.loader:

const prodConfig = {mode: 'production',devtool: 'hidden-source-map',module: {rules: [{test: /\.(css|less)$/,use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader', 'less-loader'],},],},optimization: {splitChunks: {chunks: 'all',name: false,},},plugins: [new MiniCssExtractPlugin()],
};
module.exports = merge(common, prodConfig);
  • 这样生产的配置也编写好了

生产环境devtool最佳实践是: hidden-source-map


编写scripts命令

"build": "webpack --config config/webpack.prod.js  --mode production",
"dev": "webpack serve --config config/webpack.dev.js  --mode development",

注意:热更新以前是webpack-dev-server,现在是webpack serve!!!

配置代码质量管控流程

  • 新增依赖

yarn add lint-staged @commitlint/cli @commitlint/config-conventional -D
  • 编写代码、提交检测流程

 "husky": {"hooks": {"pre-commit": "lint-staged","commit-msg": "commitlint -E HUSKY_GIT_PARAMS"}},"lint-staged": {"src/**/*.{js,jsx,ts,tsx,json,css,less,md}": ["prettier --write","eslint --fix","git add"]},"browserslist": ["ie >= 10","ff >= 30","chrome >= 34","safari >= 8","opera >= 23"]
}
  • 新增eslint配置:

//.eslintrc.js
module.exports = {root: true,parserOptions: {ecmaVersion: 7,sourceType: 'module',},parser: '@typescript-eslint/parser',plugins: ['typescript', 'react'],env: {browser: true,node: true,es6: true,},rules: {semi: ['error', 'always'], // 该规则强制使用一致的分号'no-unused-vars': 'off', // 禁止未使用过的变量'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off', //生产环境禁用 debugger'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off', //生产环境禁用 console'default-case': ['warn', { commentPattern: '^no default$' }], //要求 Switch 语句中有 Default'dot-location': ['warn', 'property'], // 强制在点号之前或之后换行eqeqeq: ['error', 'allow-null'], //要求使用 === 和 !=='new-parens': 'warn', //要求调用无参构造函数时带括号'no-caller': 'error', // 禁用 caller 或 callee'no-const-assign': 'error', //不允许改变用 const 声明的变量'no-dupe-args': 'error', //禁止在 function 定义中出现重复的参数'no-dupe-class-members': 'error', //不允许类成员中有重复的名称'no-dupe-keys': 'warn', //禁止在对象字面量中出现重复的键'no-extend-native': 'warn', //禁止扩展原生对象'no-extra-bind': 'warn', //禁止不必要的函数绑定'no-fallthrough': 'error', //禁止 case 语句落空'no-func-assign': 'warn', //禁止对 function 声明重新赋值'no-implied-eval': 'error', //禁用隐式的 eval()'no-label-var': 'error', //禁用与变量同名的标签'no-loop-func': 'error', //禁止循环中存在函数'no-mixed-operators': ['warn',{groups: [['&', '|', '^', '~', '<<', '>>', '>>>'],['==', '!=', '===', '!==', '>', '>=', '<', '<='],['&&', '||'],['in', 'instanceof'],],allowSamePrecedence: false,},], //禁止混合使用不同的操作符'no-multi-str': 'warn', //禁止多行字符串 (需要多行时用\n)'no-native-reassign': 'warn', //禁止重新分配本地对象'no-obj-calls': 'warn', //禁止将全局对象当作函数进行调用'no-redeclare': 'error', //禁止重新声明变量'no-script-url': 'warn', //禁用 Script URL'no-shadow-restricted-names': 'warn', //关键字不能被遮蔽'no-sparse-arrays': 'warn', //禁用稀疏数组'no-this-before-super': 'warn', //在构造函数中禁止在调用 super()之前使用 this 或 super'no-undef': 'error', //禁用未声明的变量'no-unexpected-multiline': 'warn', //禁止使用令人困惑的多行表达式'no-use-before-define': ['warn',{functions: false,classes: false,variables: false,},], //禁止定义前使用'no-with': 'error', //禁用 with 语句radix: 'error', //禁用函数内没有 yield 的 generator 函数'rest-spread-spacing': ['warn', 'never'], //强制限制扩展运算符及其表达式之间的空格'react/jsx-no-undef': 'error', //在 JSX 中禁止未声明的变量'react/no-direct-mutation-state': 'error', //禁止 this.state 的直接变化'react/jsx-uses-react': 'warn', //防止 React 被错误地标记为未使用'no-alert': 0, //禁止使用alert confirm prompt'no-duplicate-case': 2, //switch中的case标签不能重复'no-eq-null': 2, //禁止对null使用==或!=运算符'no-inner-declarations': [2, 'functions'], //禁止在块语句中使用声明(变量或函数)'no-iterator': 2, //禁止使用__iterator__ 属性'no-negated-in-lhs': 2, //in 操作符的左边不能有!'no-octal-escape': 2, //禁止使用八进制转义序列'no-plusplus': 0, //禁止使用++,--'no-self-compare': 2, //不能比较自身'no-undef-init': 2, //变量初始化时不能直接给它赋值为undefined'no-unused-expressions': 2, //禁止无用的表达式'no-useless-call': 2, //禁止不必要的call和apply'init-declarations': 0, //声明时必须赋初值'prefer-const': 0, //首选const'use-isnan': 2, //禁止比较时使用NaN,只能用isNaN()'vars-on-top': 2, //var必须放在作用域顶部},
};

单元测试

新增命令:

"test": "jest", //进行测试
"test-c": "jest --coverage" //生成测试报告

安装jest等依赖:

yarn add jest-environment-enzyme ts-jest@next enzyme enzyme-adapter-react-17 enzyme-to-json  @types/enzyme @types/enzyme-adapter-react-17 @types/enzyme-to-json -D

新建文件夹 test

编写第一个单元测试,引入依赖:

import App from '../src/App';
import { mount, shallow } from 'enzyme';
import React from 'react';
import toJson from 'enzyme-to-json'; //做快照

然后就可以愉快的开始写单元测试了哦

  • 这样,一个webpack5的脚手架就搭建好了,webpack内置的一些东西,可以让我们省去很多配置,看起来会更简单

????往期我的原创好文推荐

微前端的部署最佳实践(k8s + ingress)

微前端框架是怎么导入加载子应用的  【3000字精读】

熬夜准备的一个React项目升级Vite的指南

尤雨溪的5KB petite-vue源码解析

熬夜写的解析掘金新版本编辑器源码

Vite和Webpack的核心差异

CSS是如何发起攻击的?

使用require.context,实现去路由中心化管理

一行代码实现display"过渡动画"原理

在React中实现和Vue一样舒适的keep-alive

Node.js结合ProtoBuffer,从零实现一个redis! [一万字]

使用Node.js驱动Redis,实现一个消息队列!

8000字总结的前端性能优化

前端工程师学Docker ?看这篇就够了   【零基础入门 原创】

深度:手写一个WebSocket协议    [7000字]

精读:10个案例让你彻底理解React hooks的渲染逻辑

原创:如何自己实现一个简单的webpack

5000字解析:前端五种跨平台技术

如何优化你的超大型React应用 【原创精读】

前端面试官:你知道source-map的原理是什么吗?

原创:带你从零看清Node源码createServer和负载均衡整个过程

Express version 4.17核心源码解析

通过Node.js的Cluster模块源码,深入PM2原理

大前端时代,浅谈JavaScript开发重型跨平台应用以及架构

为什么我们要熟悉这些通信协议?【精读】

看完两件事

如果你觉得这篇内容对你挺有启发,我想邀请你帮我几件小事

1.点个「在看、赞、关注」,让更多人也能看到这篇内容(点了「在看」,bug -1 ????)

2.关注微信公众号「前端巅峰」,让我持续为你推送精选好文

我是Peter谭,一位小厂前端开发工程师,喜欢搞架构,对性能优化,跨平台开发有一定研究,还喜欢做自媒体,区块链。欢迎关注我

从零搭建Webpack5-react脚手架(附源码)相关推荐

  1. 【webpack系列】从零搭建 webpack4+react 脚手架(四)

    经过三个章节的学习,你已经学会搭建了一个基于webpack4的react脚手架.如果要更改配置,比如,你希望把编译后的js文件和css文件等单独放dist下的static目录下,你想想,是不是有点麻烦 ...

  2. 从零搭建 webpack4+react 脚手架

    前提条件 在开始之前,请确保安装了 Node.js 的最新版本.建议使用 Node.js 最新的长期支持版本(LTS - Long Term Support).如果你使用旧版本,你可能遇到各种问题,因 ...

  3. 关于构建umi+dva+ant react项目 附源码

    刚刚入门react,通过视频学习,做一个简单的react表格功能实现.功能满足对表格数据进行增删改,数据来源于后端接口.交互也与后端接口进行! 话不多说,直接看效果! 接口设置了30%的概率报错,出现 ...

  4. SpringBoot之从零搭建网站(可提供源码)

    前言 为什么想要搭建这个工作室? 我还记得,在大学的时候,我们往常一样的在学习过着大学生活,同往常一样的解决这某个bug,不停地问度娘,很巧的碰到了一个同行在他的博客中完美的记录了搭建网站的过程,随后 ...

  5. 关于美团:零基础搭建获利的美团饿了么优惠券CPS小程序附源码

    关于美团:零基础搭建获利的美团饿了么优惠券CPS小程序附源码 下面是无裂变版本的搭建教程. 源码地址:http://y.mybei.cn 部署步骤 部署后台,填资料 登录后台 http://q.myb ...

  6. 零基础搭建获利的美团饿了么优惠券CPS小程序(附源码)

    1.先上图 2.前言 某天下午,我正在公司认真的写着代码,突然我的手机弹了一个通知,我赶紧抓起手机看看(给自己一个摸鱼的理由) 让我看看到底是谁发消息打扰我认真的工作啊. 害,原来是某个群转发了一个外 ...

  7. arcgis开发 多版本之间如何兼容_arcgis api 4.x for js 结合 react 入门开发系列初探篇(附源码下载)...

    你还在使用 JQuery 或者 Dojo 框架开发 arcgis api 4.x for js 吗?想试试模块化开发吗?随着前端技术的发展,arcgis api 4.x for js 也有了结合 re ...

  8. 从零搭建Spring Boot脚手架:开篇以及技术选型1

    1. 前言 目前Spring Boot已经成为主流的Java Web开发框架,熟练掌握Spring Boot并能够根据业务来定制Spring Boot成为一个Java开发者的必备技巧,但是总是零零碎碎 ...

  9. springboot项目结构_从零搭建Spring Boot脚手架(1):开篇以及技术选型

    1. 前言 目前Spring Boot已经成为主流的Java Web开发框架,熟练掌握Spring Boot并能够根据业务来定制Spring Boot成为一个Java开发者的必备技巧,但是总是零零碎碎 ...

最新文章

  1. 蚂蚁森林合种计划(2020.12.26更新,7天有效)
  2. 微隔离的红蔷薇在湾区创见的舞台绽放
  3. 第十二章 支持向量机-机器学习老师板书-斯坦福吴恩达教授
  4. 使用jmeter 设计流程发起测试
  5. 《C++ Primer》14.3.1节练习
  6. AMPL 简单运输模型
  7. linux与windows共享(四)
  8. idea常用快捷键以及自定义快捷键
  9. 【C++】算法集锦(11):敏感词过滤算法(DFA)
  10. iphone编程资源站
  11. JQuery 判断浏览器及其版本
  12. Vulnhub_MoneyBox
  13. no theme named ‘sphinx_rtd_theme‘ found (missing theme.conf?)
  14. 可供量、现有量、承诺量
  15. Cocos2d-x Lua库函数剖析(二)cocos2d
  16. 怎样用计算机打出Abc,智能ABC输入法中的一些使用技巧
  17. LENOVO_WIN7_UM_32_ZH_CN_RDVD.iso
  18. 【项目管理】如何确定项目预算?
  19. JavaScript-BOM
  20. 角色所在服务器正在维护,梦幻西游角色所在服务器,角色所在服务器如何删除...

热门文章

  1. gradle自定义plugin实践之360多渠道加固打包
  2. 基于scrapy框架的关于58同城招聘网站信息的爬取
  3. Zemax 2023安装教程
  4. 泰坦服务器装系统,深海泰坦X8Ti笔记本安装win10系统操作方法
  5. java图片轮播_java制作广告图片自动轮播控件
  6. 【菜鸟教程】Zookeeper基础入门(使用curator)【下】
  7. Matlab 小球落地问题
  8. 2019全球智博会将于苏州召开,三大重磅奖项候选项目火热征集中...
  9. java 导出excle文件打不开,提示文件已损坏解决办法
  10. rock64安装docker