19、利用组件架构与构建工具开发前端应用

利用组件架构与构建工具开发前端应用

1. 组件架构构建应用

在前端开发中,组织文件是一项挑战,尤其是前端代码包含 HTML、CSS 和 JavaScript 等不同语言和文件类型。过去,开发者常按文件类型分离文件,根目录下有 css、js、img 等目录。这种方式本意良好,想将不同关注点分离,因为 HTML 标记(网站内容)、CSS(网站外观)和 JavaScript(网站响应)不同,似乎应放在不同目录。

但问题是,这些部分并非真正独立。除了一些全局样式,CSS 是为特定标记构建的。若标记被移除,相关 CSS 可能未被删除,造成空间浪费。

随着开发工具改进,组件架构模式出现。组件架构将所有相关代码组合到单个目录,通过逐个添加组件构建网页或应用,直到完成可用应用。

组件架构虽有优势,但依赖构建工具和框架。下面以 React 代码为例,展示组件架构的工作方式。

1.1 构建基本组件 - 版权声明

版权声明组件包含当前年份、版权声明和样式。以下是示例代码:

// architecture/component/simplifying-js-component/src/components/Copyright/Copyright.js
import React from 'react';
import './Copyright.css';
export default function CopyrightStatement() {
    const year = new Date().getFullYear();
    return (
        <div className="copyright">
            Copyright {year}
        </div>
    );
}

这里的标记在返回语句中,CSS 类名为 className,这是 React 框架的 JSX 语法。代码位于 src/components 目录下,每个组件有自己的目录,如 Copyright 目录包含 Copyright.css Copyright.js Copyright.spec.js

CSS 文件如下:

// architecture/component/simplifying-js-component/src/components/Copyright/Copyright.css
.copyright {
    font-size: 10px;
    margin: 1em 1em 1em 0;
    float: left;
}

版权声明组件所需的所有内容都在 Copyright 目录中,便于共享和删除。

1.2 构建稍复杂组件 - 带图标按钮

带图标按钮组件需要样式、标记、图像资产和点击动作。为使组件可复用,应尽量少硬编码选项,通过依赖注入传递点击动作。示例代码如下:

// architecture/component/simplifying-js-component/src/components/IdeaButton/IdeaButton.js
import React from 'react';
import './IdeaButton.css';
import idea from './idea.svg';
export default function IdeaButton({ handleClick, message }) {
    return (
        <button
            className="idea-button"
            onClick={handleClick}
        >
            <img
                className="idea-button__icon"
                src={idea}
                alt="idea icon"
            />
            { message }
        </button>
    );
}

在 React 中,可通过函数参数访问注入的依赖,使用解构赋值提取。同时,导入图像到变量并设置 src 属性。

1.3 构建页面组件

页面组件包含想法按钮和页脚版权声明。示例代码如下:

// architecture/component/simplifying-js-component/src/App.js
import React from 'react';
import './App.css';
import IdeaButton from './components/IdeaButton/IdeaButton';
import Copyright from './components/Copyright/Copyright';
function logIdea() {
    console.log('Someone had an idea!');
}
export default function App() {
    return (
        <div className="main">
            <div className="app">
                <IdeaButton
                    message="I have an idea!"
                    handleClick={logIdea}
                />
            </div>
            <footer>
                <Copyright />
                <IdeaButton
                    message="Footer idea!"
                    handleClick={logIdea}
                />
            </footer>
        </div>
    );
}

App.js 是主组件,位于源代码根目录,导入并组合其他组件。

组件架构的优势在于将相关代码放在一起,便于开发和维护。但它需要构建工具将组件组合成浏览器可处理的代码。

以下是组件架构开发流程的 mermaid 流程图:

graph LR
    A[开始] --> B[确定组件]
    B --> C[创建组件目录]
    C --> D[编写组件代码]
    D --> E[组合组件]
    E --> F[使用构建工具编译]
    F --> G[部署应用]
    G --> H[结束]
2. 使用构建工具组合组件

组件架构虽有优势,但无法在浏览器中直接运行,需要构建工具编译 JavaScript 代码和资产。

2.1 简化组件并准备编译

先取上一示例的简化版本,只保留 React JSX 形式的 HTML 和 JavaScript。以下是基本容器组件和版权组件代码:

// architecture/build/initial/src/App.js
import React from 'react';
import Copyright from './components/Copyright/Copyright';
export default function App() {
    return (
        <div className="main">
            <footer>
                <Copyright />
            </footer>
        </div>
    );
}

// architecture/build/initial/src/components/Copyright/Copyright.js
import React from 'react';
export default function CopyrightStatement() {
    const year = new Date().getFullYear();
    return (
        <div className="copyright">
            Copyright {year}
        </div>
    );
}

这些文件无法在浏览器中运行,需要工具将 ES6 语法和 JSX 转换为兼容代码。

2.2 安装 Babel 进行代码转换

Babel 是处理现代 JavaScript 的重要工具,可将前沿 JavaScript 转换为浏览器友好代码。安装命令如下:

npm install --save-dev babel-cli babel-preset-env babel-preset-react

创建 .babelrc 文件配置 Babel:

// architecture/build/initial/.babelrc
{ "presets": ["env", "react"] }

package.json 文件中添加脚本进行编译:

// architecture/build/initial/package.json
{
    "name": "initial",
    "version": "1.0.0",
    "description": "",
    "main": "index.js",
    "scripts": {
        "build": "babel src/index.js -o build/bundle.js"
    },
    "keywords": [],
    "author": "",
    "license": "ISC",
    "devDependencies": {
        "babel-cli": "^6.26.0",
        "babel-preset-env": "^1.6.1",
        "babel-preset-react": "^6.24.1"
    },
    "dependencies": {
        "react": "^16.1.1",
        "react-dom": "^16.1.1"
    }
}

更新 index.html 使用编译后的代码:

<!-- architecture/build/initial/index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <title>Sample</title>
</head>
<body>
    <div id="root">
    </div>
    <script src="./build/bundle.js"></script>
</body>
</html>

但打开文件会报错,因为 Babel 不包含模块加载器。

2.3 安装 Webpack 组合代码

Webpack 可处理 JavaScript 组合、CSS 或 SASS 处理和图像转换。安装 Webpack 和 Babel 加载器:

npm install --save-dev babel-loader webpack

创建 webpack.config.js 文件配置 Webpack:

// architecture/build/webpack/webpack.config.js
const path = require('path');
module.exports = {
    entry: './src/index.js',
    module: {
        loaders: [
            {
                test: /\.js?/,
                use: 'babel-loader',
            },
        ],
    },
    output: {
        filename: 'build/bundle.js',
        path: path.resolve(__dirname),
    },
};

更新 package.json 脚本调用 Webpack:

{
    "scripts": {
        "build": "webpack"
    }
}

运行脚本后,代码可在浏览器中显示。

2.4 处理 CSS 和图像

处理 CSS 时,安装 css-loader style-loader

npm install --save-dev css-loader style-loader

更新 webpack.config.js 配置 CSS 加载器:

// architecture/build/css/webpack.config.js
module: {
    loaders: [
        {
            test: /\.css$/,
            use: [
                'style-loader',
                'css-loader',
            ],
        },
        {
            test: /\.js?/,
            use: 'babel-loader',
        },
    ],
}

处理图像时,使用 file-loader 移动和重命名文件:

// architecture/build/img/webpack.config.js
module: {
    loaders: [
        {
            test: /\.svg?/,
            use: [
                {
                    loader: 'file-loader',
                    options: {
                        outputPath: 'build/',
                    },
                },
            ],
        },
        {
            test: /\.css$/,
            use: [
                'style-loader',
                'css-loader',
            ],
        },
        {
            test: /\.js?/,
            use: 'babel-loader',
        },
    ],
}

运行构建脚本,打开 index.html 即可看到组件。

构建工具处理流程如下表所示:
| 步骤 | 工具 | 操作 |
| ---- | ---- | ---- |
| 1 | Babel | 安装 babel-cli babel-preset-env babel-preset-react ,配置 .babelrc 文件 |
| 2 | Webpack | 安装 babel-loader webpack ,创建 webpack.config.js 文件配置加载器 |
| 3 | CSS 处理 | 安装 css-loader style-loader ,更新 webpack.config.js 配置 CSS 加载器 |
| 4 | 图像处理 | 使用 file-loader ,更新 webpack.config.js 配置图像加载器 |

总之,使用组件架构和构建工具可使前端开发更高效,但需逐步添加配置,耐心处理每个步骤。

3. 构建工具的进一步优化与拓展
3.1 构建工具配置的优化

随着项目的发展,构建工具的配置可能会变得复杂。为了提高构建效率和代码的可维护性,我们可以对配置进行优化。

例如,在 webpack.config.js 中,可以使用 cache 选项来缓存编译结果,避免重复编译:

// architecture/build/optimized/webpack.config.js
const path = require('path');
module.exports = {
    entry: './src/index.js',
    cache: {
        type: 'filesystem',
        buildDependencies: {
            config: [__filename]
        }
    },
    module: {
        loaders: [
            {
                test: /\.js?/,
                use: 'babel-loader',
            },
            {
                test: /\.css$/,
                use: [
                    'style-loader',
                    'css-loader',
                ],
            },
            {
                test: /\.svg?/,
                use: [
                    {
                        loader: 'file-loader',
                        options: {
                            outputPath: 'build/',
                        },
                    },
                ],
            },
        ],
    },
    output: {
        filename: 'build/bundle.js',
        path: path.resolve(__dirname),
    },
};

还可以使用 splitChunks 选项来分割代码,将公共模块提取出来,减少重复代码:

// architecture/build/optimized/webpack.config.js
// ... 其他配置
optimization: {
    splitChunks: {
        chunks: 'all',
    },
},
// ... 其他配置

以下是构建工具配置优化的步骤列表:
1. 开启缓存:在 webpack.config.js 中添加 cache 选项。
2. 代码分割:使用 splitChunks 选项将公共模块提取出来。
3. 按需加载:对于大型项目,可以使用动态导入实现按需加载。

3.2 处理更多类型的文件

除了 JavaScript、CSS 和 SVG 图像,项目中可能还会有其他类型的文件,如字体文件、JSON 文件等。我们可以通过配置 Webpack 来处理这些文件。

处理字体文件,安装 file-loader 并在 webpack.config.js 中添加配置:

// architecture/build/more-files/webpack.config.js
module: {
    loaders: [
        {
            test: /\.(woff|woff2|eot|ttf|otf)$/,
            use: [
                {
                    loader: 'file-loader',
                    options: {
                        outputPath: 'build/fonts/',
                    },
                },
            ],
        },
        // ... 其他配置
    ],
}

处理 JSON 文件,Webpack 本身支持 JSON 文件的导入,无需额外配置。

以下是处理不同类型文件的表格:
| 文件类型 | 加载器 | 配置示例 |
| ---- | ---- | ---- |
| 字体文件(woff、woff2、eot、ttf、otf) | file-loader | test: /\.(woff|woff2|eot|ttf|otf)$/, use: [{ loader: 'file-loader', options: { outputPath: 'build/fonts/' } }] |
| JSON 文件 | 无需额外配置 | 直接导入使用 |

3.3 开发环境与生产环境的区分

在开发和生产环境中,我们对构建的需求可能不同。开发环境需要快速构建和热更新,而生产环境需要优化代码和压缩文件。

可以通过 webpack-merge 来合并不同环境的配置。首先,创建 webpack.common.js webpack.dev.js webpack.prod.js 文件。

webpack.common.js 包含公共配置:

// architecture/build/environments/webpack.common.js
const path = require('path');
module.exports = {
    entry: './src/index.js',
    module: {
        loaders: [
            {
                test: /\.js?/,
                use: 'babel-loader',
            },
            // ... 其他配置
        ],
    },
    output: {
        filename: 'build/bundle.js',
        path: path.resolve(__dirname),
    },
};

webpack.dev.js 包含开发环境配置:

// architecture/build/environments/webpack.dev.js
const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');
module.exports = merge(common, {
    mode: 'development',
    devtool: 'inline-source-map',
    devServer: {
        contentBase: './dist',
    },
});

webpack.prod.js 包含生产环境配置:

// architecture/build/environments/webpack.prod.js
const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');
const TerserPlugin = require('terser-webpack-plugin');
module.exports = merge(common, {
    mode: 'production',
    optimization: {
        minimizer: [
            new TerserPlugin(),
        ],
    },
});

以下是区分开发和生产环境的 mermaid 流程图:

graph LR
    A[开始] --> B{环境类型}
    B -->|开发环境| C[使用 webpack.dev.js 配置]
    B -->|生产环境| D[使用 webpack.prod.js 配置]
    C --> E[快速构建和热更新]
    D --> F[优化代码和压缩文件]
    E --> G[开发调试]
    F --> H[部署上线]
    G --> I[结束]
    H --> I
4. 总结与展望

通过组件架构和构建工具,我们可以将前端代码组织得更加清晰,提高开发效率和代码的可维护性。组件架构将相关的 HTML、JavaScript 和 CSS 组合在一起,方便管理和复用。而构建工具则可以将这些组件编译成浏览器可处理的代码,并进行优化和压缩。

在实际项目中,我们需要根据项目的规模和需求,选择合适的组件架构和构建工具。同时,要不断学习和掌握新的技术和工具,以适应不断变化的前端开发环境。

未来,前端开发可能会朝着更加智能化、自动化的方向发展。构建工具可能会更加智能地分析代码,自动进行优化和配置。组件架构也可能会更加灵活和高效,支持更多的功能和场景。

总之,掌握组件架构和构建工具是前端开发者必备的技能,希望大家能够通过不断实践和学习,在前端开发的道路上取得更好的成绩。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值