electron-react-boilerplate 打包逻辑浅析 | 如何向公共路径添加脚本并在 html 中添加全局脚本

本文详细解释了如何在Electron应用中处理全局脚本的加载,特别是在Electron-React-Boilerplate项目中,涉及Webpack配置、公共路径设置以及如何将CDN脚本下载到本地并集成到HTML中。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


前言

随着前端技术的迅速发展,我们见证了从最初的 HTML + JS + CSS 到如今的各种前端框架的崛起。在这篇文章中,我们将探讨如何在 HTML 中添加全局脚本,特别是在 Electron 应用程序中的需求。由于很多网站使用 CDN 脚本,但在 Electron 的本地化和安全需求下,将 CDN 脚本下载到本地并在 HTML 中引用成了一个挑战。许多初学者可能不清楚如何配置它,我们将以 Electron-React-Boilerplate 为例,简要介绍打包逻辑以及如何向公共路径添加脚本。

Electron-React-Boilerplate 简介

Electron-React-Boilerplate 是一个为 Electron 应用程序提供了基础结构的项目模板。它结合了 Electron 和 React,为开发者提供了一个快速启动 Electron 项目的方式。在这个项目中,我们将重点关注如何处理全局脚本的加载和配置。

打包逻辑分析

Electron-React-Boilerplate 的打包逻辑主要基于 webpack。Webpack 是一个模块打包器,它将 JavaScript 文件及其依赖项打包成一个或多个 bundle。在 Electron-React-Boilerplate 中,webpack 负责将应用程序的源代码和相关资源打包成可在 Electron 中运行的格式。

在 webpack 的配置中,我们需要确保将全局脚本正确地引入到 HTML 中。一种常见的方法是通过 webpack 的 HtmlWebpackPlugin 插件来自动向生成的 HTML 文件中添加脚本标签。但是,对于 Electron 应用程序,我们可能需要手动控制这个过程,以便更好地管理本地资源和安全性。

向公共路径添加脚本

为了设置能在 Electron 中使用cdn脚本我打算将cdn脚本下载到本地并放置在公共路径,此时我遇到了第一问题,electron-react-boilerplate中没有public文件夹。

1. 从 electron 到 webpack 逆推

参考 https://www.electronjs.org/zh/docs/latest/tutorial/quick-start
electron 本身并没有公共路径的概念,它只是忠实的执行mian.js的指令,关键问题在于HTML文件所处的位置,即脚本从HTML开始,HTML所处的位置即是公共路径。

参考: https://webpack.js.org/guides/getting-started/
也就是说控制HTML位置的并不是 electron 而是 webpack 打包工具的配置。
为了向 Electron 应用程序的 HTML 文件中添加全局脚本,我们可以通过 webpack 的配置文件来实现。在electron-react-boilerplate中配置文件路径如下
请添加图片描述

2. 寻找公共路径

从webpack.config.renderer.dev.ts 下面的配置项中可以看到打包的输出路径在dist/renderer文件夹(release/app/dist/renderer)

output: {
    path: webpackPaths.distRendererPath,
    publicPath: '/',
    filename: 'renderer.dev.js',
    library: {
      type: 'umd',
    },
  },

已经找到了HTML所在的公共路径,但是由于在package.json中 start:renderer中使用的是 webpack serve,无法在对应路径下看到打包的文件。

"scripts": {
    "build": "concurrently \"npm run build:main\" \"npm run build:renderer\"",
    "build:dll": "cross-env NODE_ENV=development TS_NODE_TRANSPILE_ONLY=true webpack --config ./.erb/configs/webpack.config.renderer.dev.dll.ts",
    "build:main": "cross-env NODE_ENV=production TS_NODE_TRANSPILE_ONLY=true webpack --config ./.erb/configs/webpack.config.main.prod.ts",
    "build:renderer": "cross-env NODE_ENV=production TS_NODE_TRANSPILE_ONLY=true webpack --config ./.erb/configs/webpack.config.renderer.prod.ts",
    "postinstall": "ts-node .erb/scripts/check-native-dep.js && electron-builder install-app-deps && npm run build:dll",
    "lint": "cross-env NODE_ENV=development eslint . --ext .js,.jsx,.ts,.tsx",
    "package": "ts-node ./.erb/scripts/clean.js dist && npm run build && electron-builder build --publish never && npm run build:dll",
    "rebuild": "electron-rebuild --parallel --types prod,dev,optional --module-dir release/app",
    "start": "ts-node ./.erb/scripts/check-port-in-use.js && npm run start:renderer",
    "start:main": "cross-env NODE_ENV=development electronmon -r ts-node/register/transpile-only .",
    "start:preload": "cross-env NODE_ENV=development TS_NODE_TRANSPILE_ONLY=true webpack --config ./.erb/configs/webpack.config.preload.dev.ts",
    "start:renderer": "cross-env NODE_ENV=development TS_NODE_TRANSPILE_ONLY=true webpack serve --config ./.erb/configs/webpack.config.renderer.dev.ts",
    "test": "jest"
  },

我们可以创建一个新的命令 start:dist 将其中的webpack serve改成webpack
效果如下

"scripts": {
    "build": "concurrently \"npm run build:main\" \"npm run build:renderer\"",
    "build:dll": "cross-env NODE_ENV=development TS_NODE_TRANSPILE_ONLY=true webpack --config ./.erb/configs/webpack.config.renderer.dev.dll.ts",
    "build:main": "cross-env NODE_ENV=production TS_NODE_TRANSPILE_ONLY=true webpack --config ./.erb/configs/webpack.config.main.prod.ts",
    "build:renderer": "cross-env NODE_ENV=production TS_NODE_TRANSPILE_ONLY=true webpack --config ./.erb/configs/webpack.config.renderer.prod.ts",
    "postinstall": "ts-node .erb/scripts/check-native-dep.js && electron-builder install-app-deps && npm run build:dll",
    "lint": "cross-env NODE_ENV=development eslint . --ext .js,.jsx,.ts,.tsx",
    "package": "ts-node ./.erb/scripts/clean.js dist && npm run build && electron-builder build --publish never && npm run build:dll",
    "rebuild": "electron-rebuild --parallel --types prod,dev,optional --module-dir release/app",
    "start": "ts-node ./.erb/scripts/check-port-in-use.js && npm run start:renderer",
    "start:main": "cross-env NODE_ENV=development electronmon -r ts-node/register/transpile-only .",
    "start:preload": "cross-env NODE_ENV=development TS_NODE_TRANSPILE_ONLY=true webpack --config ./.erb/configs/webpack.config.preload.dev.ts",
    "start:renderer": "cross-env NODE_ENV=development TS_NODE_TRANSPILE_ONLY=true webpack serve --config ./.erb/configs/webpack.config.renderer.dev.ts",
    "start:dist": "cross-env NODE_ENV=development TS_NODE_TRANSPILE_ONLY=true webpack --config ./.erb/configs/webpack.config.renderer.dev.ts",
    "test": "jest"
  },

此时运行 npm run start:dist在对应路径下就可以看到打包的文件
请添加图片描述

3. 修改配置文件

此时距离解决问题已经只有一步之遥,在考虑如何将cdn脚本复制到release/app/dist/renderer之前,我先介绍一下electron-react-boilerplate webpack 配置文件,你需要关注开发和生产环境配置,基础配置为公共的基础配置,将cdn复制到公共路径的需求是一个公共的配置,因此需要在基础配置中添加相关配置。
请添加图片描述
我们可以使用 CopyWebpackPlugin 来将cdn或者其他你需要的脚本复制到打包后的目标路径中。这样,我们就可以确保全局脚本在应用程序运行时可用。
运行下面的命令安装webpack插件

npm install -D copy-webpack-plugin

webpack.config.base.ts修改如下

/**
 * Base webpack config used across other specific configs
 */

import path from 'path';
import webpack from 'webpack';
import TsconfigPathsPlugins from 'tsconfig-paths-webpack-plugin';
import CopyPlugin from 'copy-webpack-plugin';
import webpackPaths from './webpack.paths';
import { dependencies as externals } from '../../release/app/package.json';

const configuration: webpack.Configuration = {
  externals: [...Object.keys(externals || {})],

  stats: 'errors-only',

  module: {
    rules: [
      {
        test: /\.[jt]sx?$/,
        exclude: /node_modules/,
        use: {
          loader: 'ts-loader',
          options: {
            // Remove this line to enable type checking in webpack builds
            transpileOnly: true,
            compilerOptions: {
              module: 'esnext',
            },
          },
        },
      },
    ],
  },

  output: {
    path: webpackPaths.srcPath,
    // https://github.com/webpack/webpack/issues/1114
    library: {
      type: 'commonjs2',
    },
  },

  /**
   * Determine the array of extensions that should be used to resolve modules.
   */
  resolve: {
    extensions: ['.js', '.jsx', '.json', '.ts', '.tsx'],
    modules: [webpackPaths.srcPath, 'node_modules'],
    // There is no need to add aliases here, the paths in tsconfig get mirrored
    plugins: [new TsconfigPathsPlugins()],
  },

  plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: path.join(
            webpackPaths.rootPath,
            'assets',
            'live2dcubismcore.min.js',
          ),
          to: path.join(
            webpackPaths.distRendererPath,
            'live2dcubismcore.min.js',
          ),
        },
      ],
    }),
    new webpack.EnvironmentPlugin({
      NODE_ENV: 'production',
    }),
  ],
};

export default configuration;

参考上面的配置将live2dcubismcore.min.js路径替换为你的脚本路径即可,最终运行npm run start:dist效果如下
请添加图片描述
最后修改 src/renderer/index.ejs如下即可(将对应部分替换为你的脚本即可),index.ejs为HTML模板文件,对index.ejs的修改会同步到HTML中

<!doctype html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta
      http-equiv="Content-Security-Policy"
      content="script-src 'self' 'unsafe-inline'"
    />
    <title>Hello Electron React!</title>
    <script type="text/javascript" src="./live2dcubismcore.min.js"></script>
  </head>
  <body>
    <div id="root"></div>
  </body>
</html>

在上面的示例中,我们通过 <script> 标签将全局脚本 live2dcubismcore.min.js 引入到了 HTML 文件中。这样一来,在 Electron 应用程序运行时,全局脚本就会被加载并执行。


总结

通过以上的分析,我们了解了如何在 Electron-React-Boilerplate 中处理全局脚本的加载和配置。通过将全局脚本放置在公共路径下,并在 HTML 文件中添加相应的引用,我们可以确保 Electron 应用程序能够正常地加载并执行这些脚本。这为开发者提供了一种便捷的方式来管理 Electron 应用程序中的全局资源,同时也提高了应用程序的安全性和可维护性。

希望本文能够帮助读者更好地理解 Electron-React-Boilerplate 的打包逻辑,并在实际项目中正确地处理全局脚本的加载和配置。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

买药弟弟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值