我正在使用 typescript 和 webpack 构建 chrome 扩展,并在将最近发布的节点模块引入我的项目后开始遇到一些错误。
我安装的模块:https://github.com/gregtuc/StockSocket
加载扩展程序时浏览器中出现错误
Uncaught TypeError: Cannot read property 'bind' of undefined
堆栈跟踪
contentscript.js:35159 (./node_modules/puppeteer/lib/cjs/puppeteer/node/BrowserFetcher.js)
contentscript.js:83680 (__webpack_require__)
contentscript.js:36432 (./node_modules/puppeteer/lib/cjs/puppeteer/node/Puppeteer.js)
contentscript.js:83680 (__webpack_require__)
contentscript.js:34971 (./node_modules/puppeteer/lib/cjs/puppeteer/initialize-node.js)
contentscript.js:83680 (__webpack_require__)
contentscript.js:35022 (./node_modules/puppeteer/lib/cjs/puppeteer/node.js)
contentscript.js:83680 (__webpack_require__)
contentscript.js:24201 (./node_modules/puppeteer/cjs-entry.js)
contentscript.js:83680 (__webpack_require__)
contentscript.js:67322 (./node_modules/stocksocket/stocksocket.js)
contentscript.js:83680 (__webpack_require__)
contentscript.js:83765 (anonymous function)
contentscript.js:83792 (anonymous function)
contentscript.js:83794 (anonymous function)
...
const readdirAsync = util_1.promisify(fs.readdir.bind(fs));
const mkdirAsync = util_1.promisify(fs.mkdir.bind(fs));
const unlinkAsync = util_1.promisify(fs.unlink.bind(fs));
const chmodAsync = util_1.promisify(fs.chmod.bind(fs));
function existsAsync(filePath) {
return new Promise((resolve) => {
fs.access(filePath, (err) => resolve(!err));
});
}
...
这是我的 webpack 配置文件
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const { resolve } = require('path');
const webpack = require('webpack');
const tsRule = {
test: /\.ts(x?)$/,
exclude: /node_modules/,
use: 'ts-loader',
};
const plugins = [
new HtmlWebpackPlugin({
template: 'src/popup-page/popup.html',
filename: 'popup.html',
chunks: ['popup'],
}),
new CopyWebpackPlugin({
patterns: [{ from: 'public', to: '.' }],
}),
new CleanWebpackPlugin(),
new webpack.ProvidePlugin({
process: 'process/browser',
Buffer: ['buffer', 'Buffer'],
}),
];
module.exports = {
mode: 'development',
devtool: 'cheap-module-source-map',
resolve: {
fallback: {
path: require.resolve('path-browserify'),
util: require.resolve('util/'),
fs: false,
stream: require.resolve('stream-browserify'),
constants: require.resolve('constants-browserify'),
assert: require.resolve('assert/'),
url: require.resolve('url/'),
net: false,
tls: false,
https: require.resolve('https-browserify'),
http: require.resolve('stream-http'),
os: require.resolve('os-browserify/browser'),
zlib: require.resolve('browserify-zlib'),
child_process: false,
},
},
entry: {
popup: './src/popup-page/popup.tsx',
contentscript: './src/contentscript.tsx',
},
output: {
filename: '[name].js',
path: resolve(__dirname, 'dist'),
},
module: {
rules: [tsRule],
},
plugins,
};
这是我的 ts 配置
{
"compilerOptions": {
"target": "es6" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */,
"module": "es6" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */,
"jsx": "react" /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */,
"strict": true /* Enable all strict type-checking options. */,
"moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */,
"typeRoots": [
"./types",
"./node_modules/@types"
] /* List of folders to include type definitions from. */,
"types": [
"node"
] /* Type declaration files to be included in compilation. */,
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
"skipLibCheck": true /* Skip type checking of declaration files. */,
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
},
"exclude": ["node_modules", "typings"]
}
还有我的 contentscript.tsx 文件
import React, { FC, useState, useRef } from 'react';
import { render } from 'react-dom';
import * as CSS from 'csstype';
import StockSocket from 'stocksocket';
interface Props {}
const divBar = document.createElement('div');
divBar.className = 'mini-ticker-extension';
divBar.style.backgroundColor = 'red';
divBar.style.position = 'sticky';
divBar.style.zIndex = '100000';
divBar.style.height = '50px';
divBar.style.top = '0';
export const TickerBar: FC<Props> = () => {
interface TickerHash {}
const [tickers, setTickers] = useState<TickerHash>();
const tickerStyle: CSS.Properties = {
padding: 0,
};
const stockPriceChanged = (data: any) => {
console.log(data);
};
StockSocket.addTickers(['TSLA', 'NIO', 'NNDM', 'ETH-USD'], stockPriceChanged);
return <p style={tickerStyle}>hello world</p>;
};
render(<TickerBar />, divBar);
document.querySelector('body')?.prepend(divBar);
之前我遇到了 webpack 错误,其中 'fs'、'child-process' 或 'path' 在编译时无法解析。我找到的解决方案据说在模块导出中包含了回退。包含它们之后,我的浏览器中出现了另一个错误,无法解析“进程”和“缓冲区”,因此我找到了另一个解决方案,导致我在插件数组的 webpack 配置中需要它。我不确定我处理这些解决方案的方式是否正确,以及它们是否可能导致这个新错误。如果有人能向我解释这些错误,我将不胜感激。
链接到我的存储库:https://github.com/bryanmoon1991/mini-ticker-extension
我正在尝试构建一个扩展程序,在您当前网页的顶部放置一个小栏,显示股票行情信息,以便您可以在继续浏览的同时关注所选股票行情。
我是一名初级开发者,这是我第一次使用 webpack。
答案 0 :(得分:0)
您选择的模块 StockSocket 旨在用于 Node.js 环境而不是 Web 浏览器。出现“fs”、“childprocess”等错误是因为 StockSocket 本身(其依赖项之一)使用这些内置于 Node 中的模块,而不是浏览器。
简单地看一下 StockSocket 的源代码,它使用 puppeteer,这是一个用于控制无头 Web 浏览器的 node.js 库。这使得 StockSocket 不适合浏览器扩展。我会查看 StockSocket 的源代码,看看您是否可以使用浏览器 API 复制某些行为!