【问题标题】:how launch webpack dev server for Electron.js App如何为 Electron.js App 启动 webpack 开发服务器
【发布时间】:2022-07-04 15:21:56
【问题描述】:

我以自定义方式开发项目(为了更方便),我需要创建开发环境。 我使用 Webpack5 创建具有 HMR 模式的开发服务器。

当我启动我的脚本(配置并运行 webpack 开发服务器)时,我没有抛出任何错误,但也没有附加任何内容。

谁能帮我理解并为 Electron 应用创建 Webpack 开发服务器?

我的 webpack.config.js

import path                         from 'path'
import webpack                      from 'webpack'
import {VueLoaderPlugin}              from 'vue-loader'
import HTMLWebpackPlugin            from 'html-webpack-plugin'
import url                          from "url"
import nodeExternals                from 'webpack-node-externals'

const __filename        = url.fileURLToPath(import.meta.url)
const __dirname         = path.dirname(__filename)
const buildDir          = path.join(__dirname, '..', 'build')
const mainEntryFile     = path.join(__dirname, '..', 'src', 'main', 'main.js')
const indexHTMLFile     = path.join(__dirname, '..', 'src', 'renderer', 'index.html')
const rendererEntryFile = path.join(__dirname, '..', 'src', 'renderer', 'renderer.js')
const componentDir      = path.join(__dirname, '..', 'src', 'renderer/components')
const nodeModulesDir    = path.join(__dirname, '..', 'node_modules')
const srcDir            = path.join(__dirname, '..', 'src')

console.log('======= ComponentsDir : ' + componentDir)
console.log('======= BuildDir : ' + buildDir)
console.log('======= srcdDir : ' + srcDir)
console.log('======= mainEntryFile : ' + mainEntryFile)

let webpackConfig =
{
    entry: {
        main: mainEntryFile,
        app: rendererEntryFile
    },

    output: {
        path: buildDir,
        filename: 'main-[name].js'
    },

    mode: "development",
    devtool: 'eval',
    target: 'electron-renderer',
    // externals: [nodeExternals()],
    // stats: 'errors-only',

    node: {
        __dirname: false,
        __filename: false
    },

    resolve: {
        alias: {
            // this isn't technically needed, since the default `vue` entry for bundlers
            // is a simple `export * from '@vue/runtime-dom`. However having this
            // extra re-export somehow causes webpack to always invalidate the module
            // on the first HMR update and causes the page to reload.
            vue: "@vue/runtime-dom",
            // env: path.resolve(__dirname, `./env_${envName(env)}.json`)
            "@": srcDir,
            '@vueComponents': 'src/renderer/components'
        },
        extensions: ['.ts', '.js', '.json'],
    },

    // resolveLoader: {
    //     modules: [
    //         nodeModulesDir
    //     ]
    // },

    module: {
        rules: [
        {
            test: /\.js$/,
            exclude: /node_modules/,
            loader: 'babel-loader',
            options: {
                presets: ['@babel/preset-env']
            }
        },
        {
            test: /\.ts?$/,
            use: 'ts-loader',
            exclude: /node_modules/,
        },
        {
            test: /.vue$/,
            loader: 'vue-loader',
            options: {
                esModule: true
            }
        },
        {
            test: /\.css$/,
            use: [
                'vue-style-loader',
                'css-loader'
            ]
        }]
    },

    plugins: [
            new webpack.HotModuleReplacementPlugin(),
            new VueLoaderPlugin(),
            new HTMLWebpackPlugin({
                showErrors: true,
                cache: true,
                template: indexHTMLFile
            })
        ]
}

export default webpackConfig

我的 dev-server-webpack.js(用于启动 webpack):

import webpack                        from 'webpack'
import WebpackDevServer               from 'webpack-dev-server'
import webpackConfig                  from '../config/webpack.config.js'
import path                           from 'path'
import url                            from 'url'

console.log('---------------------------------------------')
console.log('Starting the webpack dev web server script...')
console.log('---------------------------------------------')

const __filename = url.fileURLToPath(import.meta.url);
console.log('Filename : ' + __filename)
console.log('Directory name : ' + path.dirname(__filename))

const server = new WebpackDevServer(webpack(webpackConfig), {})

server.start()

我的输出脚本登录到控制台是:

λ npm run webpack:dev                                                                                                                                                                                                                                 

> electron-vue-template@0.1.0 webpack:dev
> set NODE_ENV=development && node scripts/dev-server-webpack.js
runtime modules 54.1 KiB 24 modules
orphan modules 228 bytes [orphan] 8 modules
cacheable modules 736 KiB
  modules by path ./node_modules/ 724 KiB 35 modules
  modules by path ./src/ 11.9 KiB
    modules by path ./src/renderer/ 8.72 KiB
      modules by path ./src/renderer/components/*.vue 6.4 KiB 8 modules
      modules by path ./src/renderer/*.vue 2.11 KiB 5 modules
      ./src/renderer/renderer.js 212 bytes [built] [code generated]
    ./src/main/main.js 1.9 KiB [built] [code generated]
    ./src/service/router.ts 1.24 KiB [built] [code generated]
external "events" 42 bytes [built] [code generated]
external "electron" 42 bytes [built] [code generated]
webpack 5.66.0 compiled successfully in 4433 ms

编译 webpack 成功,但没有启动任何 chromium...

授权启动Chromium navigator(Electron)和主进程electron的机制是什么?

我不想使用 electron-webpack,因为它会规范化(因此强制结构和其他人认为不是所有项目都对应)配置、结构、选项或文件。

【问题讨论】:

  • 你没有在任何地方启动电子,你只是在启动开发服务器
  • 你是否考虑将“spawn”命令放入 webpack 中?

标签: webpack electron


【解决方案1】:

我不是 Electron 方面的专家,但是在不断尝试筛选其他资源、文档和反复试验之后,我发现了我认为从头开始的一个不错的设置。我还在制作一个安全的、非自以为是的样板文件,用于启动一个新的 Electron 应用程序,其中包含 cmets 和解释为什么某些东西按照它们的方式配置的文档。如果您想查看它,这就是我在这里引用的内容。我也很高兴收到任何人的任何反馈。 Secure Electron Boilerplate

启动Electron时,它由三部分组成:主进程、预加载脚本和渲染器。

您将分别捆绑它们,Webpack 也包含 here 的目标。

我所做的是为每个脚本使用单独的 npm 脚本,并创建一个启动脚本以由节点执行以执行额外的操作。

该脚本如下所示:

scripts/start.ts

import { config as dotenv } from 'dotenv'
import webpack from 'webpack'
import WebpackDevServer from 'webpack-dev-server'
import chalk from 'chalk'
import runScript from './runScript'
import rendererConfig from '../config/webpack.config.renderer'

dotenv({ path: '.env.local' })

const compiler = webpack(rendererConfig)
const devServerOptions: WebpackDevServer.Configuration = {
    host: 'localhost',
    hot: true,
    compress: true,
    port: process.env.PORT || 8000,
    headers: { 'Access-Control-Allow-Origin': '*' },
    static: {
        publicPath: '/',
    },
    historyApiFallback: {
        verbose: true,
    },
}
const server = new WebpackDevServer(devServerOptions, compiler)

const startServer = async () => {
    console.log(chalk.cyan('Starting preload file processing...'))
    runScript('preload', 'npm', ['run', 'start:preload'])

    console.log(chalk.cyan('Starting main process...'))
    runScript('main', 'npm', ['run', 'start:main'])

    console.log(chalk.cyan('Starting renderer server...'))
    await server.start()
}

startServer()

这基本上做了以下事情:

  • 为预加载文件生成一个运行 webpack 的进程
  • 生成一个进程来为主进程运行 webpack
  • 使用渲染器文件启动开发服务器。

这些 npm 脚本正在执行以下操作:

{
    "start": "cross-env NODE_ENV=development ts-node scripts/start.ts",
    "start:main": "cross-env NODE_ENV=development electronmon -r ts-node/register ./src/main/main.ts",
    "start:preload": "webpack --config config/webpack.config.preload.ts",
}

单个 npm start 调用会在实际启动服务器之前运行其他两个进程,因为它们是应用程序运行所必需的。现在,如果您在从前端调用 NodeJS 模块时确实需要使用预加载文件,则只需要它。

这是怎么回事:

  • 预加载文件被捆绑到 JavaScript 中,以便 Chromium 浏览器在 Electron 中加载它。
  • Electron 在主入口文件上使用electromon 启动。

现在,在src/main/main.ts 文件中,或者主窗口中Electron 的入口文件所在的任何位置。在 preload 属性上,您需要指定 webpack 输出捆绑文件的位置。我根据应用程序是否打包指定了一个三元运算符。如果未打包,则文件位置与原始文件位置相邻,扩展名为 .dev,因为它仅用于开发。

src/main/window.ts

import { app } from 'electron'
import { join } from 'path'

...

let mainWindow = new BrowserWindow({
    ...,
    webPreferences: {
        preload: app.isPackaged
            ? join(__dirname, 'preload.js')
            : join(srcPreloadPath, 'preload.dev.js'),
    }
})

...

如果您想查看 webpack 配置是什么,请查看我在顶部链接的 repo。我希望这对你和任何努力学习 Electron 的人有所帮助。我也在学习中,如有错误请指出!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-09-18
    • 1970-01-01
    • 2018-10-23
    • 2020-05-19
    • 2020-06-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多