不妨放弃 create-react-app,学习一下 Webpack。
由 Mux 赞助的 DEV 全球展示挑战赛:展示你的项目!
最近我在读Alex Banks 和 Eve Porcello 合著的《Learning React》,其中有一章详细介绍了如何在不使用 create-react-app 的情况下搭建 React 项目,我觉得了解底层工作原理是一件很棒的事情。
对于那些无法阅读这本书的人来说,我认为撰写相关文章是个好主意,因为文章很容易获取。
PS:尽管如此,这本书还是物有所值的。
另外,我假设你们都应该知道如何使用 Node.js 自带的包管理器 (npm)。
现在让我们看看如何创建我们自己的 React 应用程序
1. 项目设置
首先使用 `npm init` 初始化 package.json 文件,以便安装模块。我们将安装启动所需的初始依赖项。
npm init -y
npm install --save react react-dom serve
现在我们开始搭建框架(更像是文件夹结构)。如果您是新手或者之前从未使用过 webpack,我建议您跟着步骤操作。
> node_modules
> package.json
> package-lock.json
> /src (folder)
> index.js
> /components (folder)
> App.js
> Banner.js
> Header.js
这是我们的项目文件夹,它有一个非常基本的设置,包括一个 src 文件夹,其中包含 index.js 文件(这将是我们的入口点)和一个 components 文件夹,其中包含 App、Banner 和 Header 组件。
应用程序的结构有很多种,这只是一个非常基本、易于理解的结构。
2. 项目制作
我们的项目将包含页眉和横幅。那么,让我们先从创建页眉组件开始。
// ./src/components/Header.js
import React from 'react';
export default function Header() {
return (
<header>
<h2>Checkout these lovely Unicorns</h2>
</header>
);
}
现在是横幅组件
// ./src/components/Banner.js
import React from 'react';
export default function Banner() {
return (
<section>
🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄Unicorns For SALE🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄🦄
</section>
);
}
将这些组件添加到App.js中,然后使用 ReactDOM.render() 通过 index.js 渲染 App 组件。
// ./src/components/App.js
import React from 'react';
import Header from './Header';
import Banner from './Banner';
export default function App() {
return (
<>
<Header />
<Banner />
</>
);
}
// ./src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './components/App';
ReactDOM.render(<App />, document.getElementById('root'));
现在我们已经完成了 React 组件的编写,让我们进入下一步吧。
3. 配置 Webpack
由于我们的组件被拆分成不同的模块,我们将使用 webpack 这个模块打包工具。我们不能直接把所有内容写在一个文件中,那样会使开发变得混乱,所以我们使用模块打包工具将所有内容打包成一个大文件,以便在生产环境中使用。
首先,让我们安装 webpack 和 webpack-cli 作为开发依赖项。
npm install webpack webpack-cli --save-dev
所以,理解 webpack 本身就是一个值得深入探讨的话题,但我会尽量提供一个概览。你可以看到,到处都有 import 语句,因此 webpack 会从我们在 webpack.config 文件(index.js)中定义的入口点开始查找,并在遇到任何 import 语句时开始构建依赖关系图。简单来说,webpack 会说:“哦,这个模块需要那个模块,而那个模块又需要另一个模块。” 然后,它会将所有内容打包到一个大文件中。
现在让我们构建最基本的webpack.config.js文件
// ./webpack.config.js
var path = require("path");
module.exports = {
mode: "development",
entry: "./src/index.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "bundle.js"
}
};
这个配置文件包含一个入口点和一个输出路径,我们告诉 webpack从 index.js 开始查找并打包所有内容(基于依赖关系图),并将输出放在名为 dist 的文件夹中的 bundle.js 文件中。我们还将模式设置为开发模式,因此目前不会进行任何压缩和生产相关的操作。
现在 webpack 已经准备好打包我们的文件了,但由于我们编写的是 JSX 并且使用的是现代 JavaScript,所以我们需要一个加载器将这些内容转换成所有浏览器(无论新旧)都能理解的语法。这里我们将使用Babel 加载器。
npm install babel-loader @babel/core --save-dev
现在我们将更新 webpack 配置文件以使用此加载器。
module.exports = {
mode: "development",
entry: "./src/index.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "bundle.js"
},
module: {
rules: [{ test: /\.js$/, exclude: /node_modules/, use: "babel-loader" }]
}
};
rules 属性用于添加各种用途的加载器(即 JavaScript 对象)(我们最后还会添加 Sass 加载器)。
这里我们只添加了 Babel 加载器,它有一个 test 属性,用于判断是否遇到任何 .js 文件,如果该文件位于 node_modules 文件夹中,则使用 Babel 加载器加载它。
Webpack 现在一切就绪。最后一步是创建一个.babelrc文件,指定 Babel 要执行的转换预设。这里我们需要将 ESNext(现代 JavaScript)语法转换为所有浏览器都能理解的语法,同时也要转换 JSX。我们可以通过以下方式实现。
// ./.babelrc
{
"presets": ["@babel/preset-env", "@babel/preset-react"]
}
4. 运行 webpack
安装 webpack-cli 后,您可以像这样从终端运行 webpack。
npx webpack
这将创建一个 dist 目录,并按照配置文件中的说明,在开发模式下创建 bundle.js 文件。准备发布时,请将模式更改为生产模式;或者,通常的做法是在 package.json 文件中创建脚本。
// ./package.json
...
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack --mode production"
},
...
在这种情况下,请这样做npm run build。
5. 创建 HTML 文件
在这里我们将创建index.html文件,它会链接到 bundle.js 文件。我把它放在 dist 文件夹中。
// ./dist/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Unicorn Stable</title>
</head>
<body>
<div id="root"></div>
<script src="./bundle.js"></script>
</body>
</html>
最终的文件夹结构如下所示
> node_modules
> package.json
> package-lock.json
> /dist (folder)
> bundle.js
> index.html
> /src (folder)
> index.js
> /components (folder)
> App.js
> Banner.js
> Header.js
现在,在浏览器中打开 HTML 文件,你会看到,如果一切顺利,独角兽促销活动正在进行中🦄。
6. 添加 Sass
让我们给组件添加一些样式。我们将使用一个 Sass 文件,但您也可以为每个组件使用单独的 Sass 文件,因为我们只需要导入它们,webpack 会自动使用合适的加载器将它们打包。
/* ./src/styles.scss */
h2 {
background-color: #a0c3f0;
font-size: 200%;
text-align: center;
}
section {
border: 2px dotted #ac307c;
font-size: 150%;
text-align: center;
padding: 1em;
}
然后我们将它们导入到我们的应用程序组件中。
import React from 'react';
import Header from './Header';
import Banner from './Banner';
import '../styles.scss';
....
现在让我们安装必要的加载器,我们需要style-loader、css-loader 和 sass-loader(它依赖于 node-sass)。
npm install --save-dev style-loader css-loader sass-loader node-sass
然后我们更新 webpack 配置文件,检查 .scss 文件并按设定的顺序应用加载器。
var path = require('path');
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
},
module: {
rules: [
{ test: /\.js$/, exclude: /node_modules/, use: 'babel-loader' },
{
test: /\.scss$/,
use: ['style-loader', 'css-loader', 'sass-loader'],
},
],
},
};
顺序要保持不变,sass-loader 需要先应用,然后是 css-loader,最后是 style-loader(最后一个应用得最先)。
让我们最后打包一下代码,npx webpack然后检查浏览器。所有样式都应该已经应用好了 :)