潇何 發表於 2021-2-28 14:13:00

从零开始使用 webpack5 搭建 react 项目

<blockquote>
<p>本文的示例项目源码可以点击 这里 获取</p>
</blockquote>
<h2 id="一前言">一、前言</h2>
<p>webpack5 也已经发布一段时间了,其模块联邦、bundle 缓存等新特性值得在项目中进行使用。经过笔者在公司实际项目中的升级结果来看,其提升效果显著,热更新时间由原来的 8s 减少到了 2s,会极大的提升开发幸福感。除此之外,webpack5 也带来了更好的 tree shaking 算法,项目的打包体积也会进一步减少,提升用户体验。</p>
<p>目前来看,create-react-app 脚手架还没有适配 webpack5,如果你想熟悉下如何从零开始配置 webpack5 项目的话,不妨跟着文档操作一下。</p>
<h2 id="二项目初始化">二、项目初始化</h2>
<h3 id="21-初始化文件结构">2.1 初始化文件结构</h3>
<p>首先创建一个文件夹,进行 npm 初始化</p>
<pre><code class="language-bash">mkdir react-webpack5-template
cd react-webpack5-template
# npm 初始化配置
npm init -y
# 创建 webpack 配置文件
touch webpack.common.js
# 创建 babel 配置文件
mkdir src &amp;&amp; cd src
# 创建入口文件
touch index.js
cd .. &amp;&amp; mkdir build
touch index.html
</code></pre>
<p>在上述步骤执行完毕之后,你的目录结构应该如下所示:</p>
<pre><code>├── src
│&nbsp;&nbsp; └── index.js
├── build
│&nbsp;&nbsp; └── index.html
├── webpack.common.js
├── .babelrc
├── package.json
</code></pre>
<p>随后安装必要的依赖</p>
<pre><code class="language-bash">npm i webpack webpack-cli webpack-dev-server html-webpack-plugin babel-loader path -D
npm i react react-dom
</code></pre>
<h3 id="22-完善配置文件">2.2 完善配置文件</h3>
<p>文件结构生成完毕后,我们开始编写代码。首先,在<code>index.js</code> 中写入以下代码:</p>
<pre><code class="language-jsx">import React from 'react';
import ReactDOM from 'react-dom';

ReactDOM.render(
&lt;React.StrictMode&gt;
    &lt;div&gt;你好,React-webpack5-template&lt;/div&gt;
&lt;/React.StrictMode&gt;,
document.getElementById('root')
);
</code></pre>
<p>在<code> webpack.common.js</code> 中写入以下内容:</p>
<pre><code class="language-js">const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = (env) =&gt; {
return {
    mode: "development",
    entry: {
      index: './src/index.js'
    },
    output: {
      // 打包文件根目录
      path: path.resolve(__dirname, "dist/"),
    },
    plugins: [
      // 生成 index.html
      new HtmlWebpackPlugin({
      filename: "index.html",
      template: "./build/index.html",
      }),
    ],
    module: {
      rules: [
      {
          test: /\.(jsx|js)?$/,
          use: ["babel-loader"],
          include: path.resolve(__dirname, 'src'),
      },
      ]
    },
    devServer: {
      port: 8080,
      host: '0.0.0.0',
    },
}
}
</code></pre>
<p>在 index.html 中写入以下代码:</p>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
    &lt;meta charset="UTF-8"&gt;
    &lt;title&gt;Title&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;div id="root"&gt;&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<p>在 .babalrc 中写入以下代码:</p>
<pre><code class="language-json">{
"presets": ["@babel/preset-react"]
}
</code></pre>
<p>然后在 package.json 中添加如下 script:</p>
<pre><code class="language-diff">"scripts": {
"test": "echo \"Error: no test specified\" &amp;&amp; exit 1",
+"dev": "webpack serve --config webpack.common.js"
},
</code></pre>
<p>随后我们运行 <code>npm run dev</code> 就可以直接运行了,由于我们上面设置的 devServer 端口号为 8080,所以在浏览器中打开 <code>localhost:8080</code> 即可看到如下效果:</p>
<p><img src="https://file.lcs.show/image/20210228004903.png" alt="image-20210228004846012" loading="lazy"></p>
<p>到这里位置,我们的初步搭建已经完成了,但是我们在现有的项目中看到的 webpack 配置文件不止这些,有 less、css 文件的解析,image 等资源文件的处理,还有一些优化项的配置等,接下来会一一介绍。</p>
<h2 id="三功能性配置">三、功能性配置</h2>
<p>上面我们已经做到可以将一个简单的 React 项目运行起来了,接下来我们要做的是加一些功能。</p>
<h3 id="31-样式文件解析">3.1 样式文件解析</h3>
<p>在前端项目开发过程中,比较经常使用的是 css、less、scss、sass、stylus,下面我们就先仅对 less 进行配置,其余的样式文件可参考 GitHub 源码。首先安装 loader:</p>
<pre><code class="language-bash">npm i style-loader less-loader less css-loader postcss-loader postcss-normalize autoprefixer postcss-preset-env -D
</code></pre>
<p>首先,在 webpack.common.js 顶部加入以下正则表达式,用来判断样式文件:</p>
<pre><code class="language-js">// less/less module 正则表达式
const lessRegex = /\.less$/;
const lessModuleRegex = /\.module\.less$/;
</code></pre>
<p>然后在 webpack.common.js 中加入以下配置:</p>
<pre><code class="language-js">module: {
        rules: [
    {
      test: lessRegex,
      use: ["style-loader", "css-loader", "postcss-loader", "less-loader"],
      sideEffects: true,
    },
]
}
</code></pre>
<p>新增 postcss.config.js 文件并配置:</p>
<pre><code class="language-js">const postcssNormalize = require('postcss-normalize');

module.exports = {
plugins: [
    [
      "postcss-preset-env",
      {
      autoprefixer: {
          flexbox: "no-2009",
      },
      stage: 3,
      }
    ],
    postcssNormalize(),
    require('autoprefixer') ({
      overrideBrowserslist: ['last 2 version', '&gt;1%', 'ios 7']
    })
],
};
</code></pre>
<p>然后我们在 src 目录下新建 index.less 文件,测试配置是否成功:</p>
<pre><code class="language-less">// index.less
.title {
text-align: center;
color: coral;
}
</code></pre>
<p>重新运行项目后发现样式生效,配置成功。</p>
<p><img src="https://file.lcs.show/image/20210228102930.png" alt="image-20210228102928287" loading="lazy"></p>
<p>但是仅配置 less 是不够的,我们日常在开发过程中经常用到 less module,在这里我们进行如下配置,首先安装 <code>react-dev-utils</code>:</p>
<pre><code class="language-bash">npm i react-dev-utils resolve-url-loader -D
</code></pre>
<p>在 webpack.common.js 中进行如下配置:</p>
<pre><code class="language-diff">const getCSSModuleLocalIdent = require("react-dev-utils/getCSSModuleLocalIdent");

module: {
        rules: [
    {
      test: lessRegex,
+   exclude: lessModuleRegex,
      use: ["style-loader", "css-loader", "postcss-loader", "less-loader"],
      sideEffects: true,
    },
+   {
+   test: lessModuleRegex,
+   use: [
+       "style-loader",
+       {
+         loader: "css-loader",
+         options: {
+         modules: {
+             getLocalIdent: getCSSModuleLocalIdent,
+         }
+         }
+       },
+       "postcss-loader",
+       "less-loader"
+   ],
+   }
]
}
</code></pre>
<p>接下来我们新建 index.module.less 来进行测试:</p>
<pre><code class="language-less">.font {
color: red;
}
</code></pre>
<p>重新运行项目后样式生效,并且 className 也发生了相应变化:</p>
<p><img src="https://file.lcs.show/image/20210228110626.png" alt="image-20210228110624352" loading="lazy"></p>
<p>CSS、SCSS 与 SASS 的配置都大同小异,大家可以移步到我的 GitHub。</p>
<h3 id="32-图片地址解析">3.2 图片地址解析</h3>
<blockquote>
<p>资源模块(asset module)是一种模块类型,它允许使用资源文件(字体,图标等)而无需配置额外 loader。</p>
<p>在 webpack 5 之前,通常使用:</p>
<ul>
<li><code>raw-loader</code> 将文件导入为字符串</li>
<li><code>url-loader</code> 将文件作为 data URI 内联到 bundle 中</li>
<li><code>file-loader</code> 将文件发送到输出目录</li>
</ul>
<p>资源模块类型(asset module type),通过添加 4 种新的模块类型,来替换所有这些 loader:</p>
<ul>
<li><code>asset/resource</code> 发送一个单独的文件并导出 URL。之前通过使用 <code>file-loader</code> 实现。</li>
<li><code>asset/inline</code> 导出一个资源的 data URI。之前通过使用 <code>url-loader</code> 实现。</li>
<li><code>asset/source</code> 导出资源的源代码。之前通过使用 <code>raw-loader</code> 实现。</li>
<li><code>asset</code> 在导出一个 data URI 和发送一个单独的文件之间自动选择。之前通过使用 <code>url-loader</code>,并且配置资源体积限制实现。</li>
</ul>
<p>—— 引自 webpack5 中文文档</p>
</blockquote>
<p>webpack5 内置 assets 类型,我们不需要额外安装插件就可以进行图片等资源文件的解析,配置如下:</p>
<pre><code class="language-javascript">{
test: /\.(jpe?g|png|gif|svg|woff|woff2|eot|ttf|otf)$/i,
type: "asset/resource",
},
</code></pre>
<p>如此我们便可以处理引入的图片资源文件,可以根据自身需要进行拓展。</p>
<h2 id="四性能优化">四、性能优化</h2>
<h3 id="4-1-引入缓存">4. 1 引入缓存</h3>
<p>前面提到,webpack5 引入了缓存来提高二次构建速度,我们只需要在 webpack 配置文件中加入如下代码即可开心缓存</p>
<pre><code class="language-js">cache: {
type: 'filesystem',
// 可选配置
buildDependencies: {
    config: , // 当构建依赖的config文件(通过 require 依赖)内容发生变化时,缓存失效
},
name: 'development-cache',
},
</code></pre>
<p>重新运行项目后会发现 node_modules 目录下会新增一个 .cache 文件夹:</p>
<p><img src="https://file.lcs.show/image/20210228114441.png" alt="image-20210228114440107" loading="lazy"></p>
<p>笔者在实际项目中测试,热更新时间由原来的 8s 缩短到 2s 可以说是提升巨大。</p>
<h2 id="五总结">五、总结</h2>
<p>到目前为止,配置工作算是已经完成了,本篇文章只是指导大家进行一些初始化配置,项目中肯定还有很多可以优化的地方,比如说分别配置 webpack.dev.js 以及 webpack.prod.js 以通过测试环境与正式环境的不同需求,在这里就不细说,环境区分的相关配置我会上传到 GitHub 中,如果你觉得项目对你有点用处的话,还请点个 star。</p>


</div>
<div id="MySignature" role="contentinfo">
    我不管,JS天下第一<br><br>
来源:https://www.cnblogs.com/Jacob98/p/14458896.html
頁: [1]
查看完整版本: 从零开始使用 webpack5 搭建 react 项目