在Electron的预装脚本中使用typescript

时间:2018-03-02 19:25:50

标签: typescript electron

我使用电子伪造的react-typescript模板构建了一个Electron应用程序,这意味着它使用了电子预编译,根据the only documentation I can find,它应该可以工作。

index.html包含正常工作的打字稿,如广告所述。但我也使用带有预加载脚本的webview tag,以显示外部网站并对其进行修改。这是我使用的代码:

<webview id="webview" preload="./preload.ts" webpreferences="contextIsolation, webSecurity=no" src="https://example.com"></webview>

这个预装脚本非常复杂,我很乐意使用打字稿。但它显然被解析为javascript,任何类型的注释都会导致语法错误。是否有一个技巧使这个工作与打字稿?如果我必须手动调用转换器,如何将其与电子伪造的构建过程集成?

tl; dr :preload脚本被解析为javascript尽管是打字稿&#34;只是工作&#34;在其他地方,我也想在这里使用打字稿

3 个答案:

答案 0 :(得分:1)

预加载脚本是另外一种,你不能直接在那里指点打字稿。只有可能的方法是使javascript预装脚本bootstraps电子编译在其中(因为你使用的是电子预编译),并且需要在其中使用typescript文件。它有点冗长,需要额外的开销,老实说,我并不强烈推荐它。

答案 1 :(得分:0)

您可以在预加载文件(或任何文件)中使用TypeScript。只需导入ts-node程序包并对其进行配置,然后再导入任何TypeScript代码。

F.e。创建一个包含以下内容的index.js文件:

require('./require-hooks')
module.exports = require('./entry') // this is your TypeScript entry point.

然后在您的require-hooks.js文件中配置ts-node(ts-node是一个需要钩子,可以动态编译TypeScript,并为后续运行提供缓存):

// ability to require/import TypeScript files
require('ts-node').register({
  typeCheck: false, // faster, no type checking when require'ing files. Use another process to do actual type checking.
  transpileOnly: true, // no type checking, just strip types and output JS.
  files: true,

  // manually supply our own compilerOptions, otherwise if we run this file
  // from another project's location then ts-node will use
  // the compilerOptions from that other location, which may not work.
  compilerOptions: require('./tsconfig.json').compilerOptions,
})

请注意,您可以在其中放置各种要求钩子,例如,您可以执行诸如require('path/to/file.ts')require('path/to/file.tsx')require('path/to/file.jsx')require('path/to/file.png'),{{ 1}}等,您可以在其中定义用于处理某些类型的文件的挂钩(在某种程度上类似于Webpack,但是挂钩到Node的内置require('path/to/file.mp3')函数中)。例如,@babel/register是用于通过Babel运行JS文件的钩子,asset-require-hook是允许您导入JPG文件之类的资产的require钩子,yaml-hook允许您require require个文件。编辑:更多:css-modules-require-hook用于导入CSS模块,module-alias用于创建别名,如WebPack。

pirates库是一种流行的工具,用于制作您自己的需求挂钩,尽管我也发现无需库即可手动制作挂钩。例如,您可以重写.yaml来实现一些简单的挂钩:

Module.prototype.require

然后在其他文件中

const path = require('path')
const url = require('url')
const Module = require('module')
const oldRequire = Module.prototype.require

function toFileURL(filePath) {
  return url.format({
    pathname: filePath,
    protocol: 'file:',
    slashes: true,
  })
}

Module.prototype.require = function(moduleIdentifier) {
  // this simple hook returns a `file://...` URL when you try to `require()`
  // a file with extension obj, svg, png, or jpg.
  if (['.obj', '.png', '.svg', '.jpg'].some(ext => moduleIdentifier.endsWith(ext))) {
    const result = String(toFileURL(path.resolve(path.dirname(this.filename), moduleIdentifier)))

    result.default = result
    return result
  } else {
    return oldRequire.call(this, moduleIdentifier)
  }
}

您甚至可以将对const fs = require('fs') const img = require('path/to/foo.jpg') console.log(img) // file:///absolute/path/to/foo.jpg document.createElement('img').src = img 的调用移到覆盖的document.createElement('img').src = img方法中以自动执行该操作,然后返回require元素,而不返回一个img URL。 :)

最后,在上述file://文件导入的./entry.ts文件中,您可以在其中输入任何TypeScript。

答案 2 :(得分:0)

我的解决方案是添加第二个Webpack配置,以输出单个inject.js文件。

src/inject.ts从=> dist/inject.js的地方转换成这样:

new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: false,
      enableRemoteModule: false,
      contextIsolation: true,
      sandbox: true,
      preload: path.join(__dirname, 'mercari_inject.js')
    }
});

使用如下基本配置webpack.main.config.js

module.exports = {
    ...
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: '[name].js'
    },
    ...
}

主配置webpack.main.config.js应该如下所示:

const merge = require('webpack-merge');
const baseConfig = require('./webpack.base.config');

const mainConfig = merge.smart(baseConfig, {...})
const injectScriptConfig = merge.smart(baseConfig, {
  target: 'electron-preload',
  entry: {
    inject: './src/inject.ts',
  },
  module: {
    rules: [
       ... // babel/typescript loaders
    ]
  } 
})

module.exports = [
   mainConfig,
   injectScriptConfig,
]

请注意,在导出之前从单个配置对象更改为阵列。

module.exports = {...}
module.exports = [{...}, {...}]