Browse Source
Merge in VISUAL/fineui from ~TREECAT/fineui:es6 to es6 * commit 'b367f07bb020e9895a421078649ce0117ed6ee0b': KERNEL-14512 chore:打包结构调整 KERNEL-14512 chore:打包结构调整 KERNEL-14512 chore:打包调整 KERNEL-14512 chore:打包调整 KERNEL-14512 chore: 代码结构调整 KERNEL-14512 chore: fineui.worker.js KERNEL-14512 chore: demo 支持 build KERNEL-14316 chore: 代码调整 KERNEL-14316 fix: jQuery 升级及 worker 缺失的问题es6
treecat-罗群
2 years ago
29 changed files with 469 additions and 129 deletions
@ -0,0 +1,58 @@
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin'); |
||||
const path = require('path'); |
||||
const TerserPlugin = require("terser-webpack-plugin"); |
||||
const webpack = require("webpack"); |
||||
const childProcess = require("child_process"); |
||||
|
||||
function git(command) { |
||||
return childProcess.execSync(`git ${command}`).toString().trim(); |
||||
} |
||||
|
||||
module.exports = { |
||||
mode: 'production', |
||||
entry: { |
||||
"demo.min": './src/index.js' |
||||
}, |
||||
module: { |
||||
rules: [ |
||||
{ |
||||
test: /\.js$/, |
||||
exclude: /node_modules/, |
||||
use: { |
||||
loader: 'babel-loader', |
||||
}, |
||||
}, |
||||
{ |
||||
test: /\.less$/i, |
||||
use: ['style-loader', 'css-loader', 'less-loader'], |
||||
}, |
||||
], |
||||
}, |
||||
devtool: 'source-map', |
||||
resolve: { |
||||
extensions: ['.js', '.ts'], |
||||
alias: { |
||||
'@': path.resolve(__dirname, './src'), |
||||
}, |
||||
}, |
||||
optimization: { |
||||
usedExports: false, |
||||
minimize: true, |
||||
minimizer: [ |
||||
new TerserPlugin({ |
||||
include: /\.min/, |
||||
parallel: true, |
||||
terserOptions: { |
||||
output: { |
||||
comments: false, |
||||
}, |
||||
}, |
||||
}), |
||||
new webpack.BannerPlugin({ |
||||
banner: `time: ${new Date().toLocaleString("en-US")}; branch: ${git( |
||||
"name-rev --name-only HEAD" |
||||
)} commit: ${git("rev-parse HEAD")}`,
|
||||
}) |
||||
], |
||||
}, |
||||
}; |
@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env node
|
||||
const yargs = require('yargs/yargs'); |
||||
const { hideBin } = require('yargs/helpers'); |
||||
|
||||
const workerCmd = require('./worker/cli.worker'); |
||||
|
||||
const argv = yargs(hideBin(process.argv)).argv; |
||||
|
||||
const cmd = argv._[0]; |
||||
|
||||
const cmds = new Map([ |
||||
['worker', workerCmd], |
||||
]); |
||||
|
||||
if (!cmd) throw new Error('Command is undefined!'); |
||||
|
||||
if (cmds.has(cmd)) { |
||||
cmds.get(cmd)?.exec(argv); |
||||
} else { |
||||
throw new Error(`Command ${cmd} not supported`); |
||||
} |
@ -0,0 +1,76 @@
|
||||
const fs = require('fs'); |
||||
const path = require('path'); |
||||
|
||||
function first2UpperCase(str) { |
||||
return str.toLowerCase().replace(/( |^)[a-z]/g, L => L.toUpperCase()); |
||||
} |
||||
|
||||
function scanAndCreate(structure, workerName, root) { |
||||
Object.keys(structure) |
||||
.forEach(name => { |
||||
if (typeof structure[name] === 'object') { |
||||
fs.mkdirSync(path.resolve(root, name)); |
||||
|
||||
scanAndCreate(structure[name], workerName, path.resolve(root, `./${name}`)); |
||||
} else if (structure[name] === '') { |
||||
fs.appendFileSync(path.resolve(root, name), ''); |
||||
} else if (typeof structure[name] === 'string') { |
||||
let content = fs.readFileSync(structure[name]).toString(); |
||||
|
||||
content = content |
||||
.replace(/\${WorkerName}/g, first2UpperCase(workerName)) |
||||
.replace(/\${workerName}/g, workerName); |
||||
|
||||
fs.appendFileSync(path.resolve(root, name), content); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
module.exports = { |
||||
exec: async args => { |
||||
if (!args.init) { |
||||
throw new Error(`Command init not found in args`); |
||||
} |
||||
|
||||
if (!args.name) { |
||||
throw new Error('Command --name=... not found in args'); |
||||
} |
||||
|
||||
const name = args.name; |
||||
|
||||
const structure = { |
||||
[`${name}_worker`]: { |
||||
'main_thread': { |
||||
action: { |
||||
'action.worker_ability_test.ts': path.resolve(__dirname, './template/main_thread/action/action.worker_ability_test.t'), |
||||
}, |
||||
[`${name}_main_thread.ts`]: path.resolve(__dirname, './template/main_thread/main_thread.t'), |
||||
}, |
||||
utils: { |
||||
'action_type.ts': path.resolve(__dirname, './template/utils/action_type.t'), |
||||
'payload_type.ts': path.resolve(__dirname, './template/utils/payload_type.t'), |
||||
}, |
||||
'worker_thread': { |
||||
action: { |
||||
'action.worker_ability_test.ts': path.resolve(__dirname, './template/worker_thread/action/action.worker_ability_test.t'), |
||||
}, |
||||
[`${name}_worker_thread.ts`]: path.resolve(__dirname, './template/worker_thread/worker_thread.t'), |
||||
}, |
||||
[`${name}_main_thread.helper.ts`]: path.resolve(__dirname, './template/main_thread.helper.t'), |
||||
}, |
||||
}; |
||||
|
||||
scanAndCreate(structure, name, args.where ? path.resolve(args.where) : process.cwd()); |
||||
}, |
||||
}; |
||||
|
||||
// 结构
|
||||
// -xxx_worker
|
||||
// -|--main_thread
|
||||
// -|--|--action
|
||||
// -|--|--xxx_main_thread.ts
|
||||
// -|--utils
|
||||
// -|--|--action_type.ts
|
||||
// -|--worker_thread
|
||||
// -|--|--action
|
||||
// -|--|--worker_main_thread.ts
|
@ -0,0 +1,48 @@
|
||||
import { ${WorkerName}MainThreadWorker } from './main_thread/${workerName}_main_thread'; |
||||
// 不需要一起打包的话则不需要引入这行 |
||||
// FuiWorkerPlugin中的属性会同步到fui-worker中,同时支持loader行内传入属性 |
||||
// 根据实际需求传入inline,返回格式 true -> blob url,false -> servicePath |
||||
import workerUrl from 'fui-worker!./worker_thread/${workerName}_worker_thread'; |
||||
|
||||
export class ${WorkerName}WorkerHelper { |
||||
private worker: ${WorkerName}MainThreadWorker; |
||||
|
||||
/** |
||||
* 拿到helper中的worker |
||||
*/ |
||||
public getWorker() { |
||||
if (this.worker) { |
||||
return this.worker; |
||||
} |
||||
|
||||
this.worker = BI.Workers.createWorker(${WorkerName}MainThreadWorker, { |
||||
workerUrl: this.urlFormatter(workerUrl), |
||||
workerName: BI.UUID(), |
||||
}); |
||||
|
||||
return this.worker; |
||||
} |
||||
|
||||
/** |
||||
* 格式化worker url,比如补充一些环境信息到参数里 |
||||
* 可通过 #hash 将参数传入blob url |
||||
* @param url worker url |
||||
*/ |
||||
private urlFormatter(url: string) { |
||||
return url; |
||||
} |
||||
|
||||
/** |
||||
* 终止worker |
||||
*/ |
||||
public terminate() { |
||||
this.worker?.terminate(); |
||||
} |
||||
} |
||||
|
||||
// 使用示例 |
||||
// const workerHelper = new ${WorkerName}WorkerHelper(); |
||||
|
||||
// workerHelper.getWorker() |
||||
// .testCommunication() |
||||
// .then(res => console.log(res)); |
@ -0,0 +1,13 @@
|
||||
import { WorkerAbilityTestActionType } from '../../utils/action_type'; |
||||
import { WorkerAbilityTestPayload, WorkerAbilityTestReponse } from '../../utils/payload_type'; |
||||
|
||||
export class WorkerAbilityTestMainThreadAction extends BI.Workers.WorkerBaseAction { |
||||
/** |
||||
* 通信能力检测 |
||||
*/ |
||||
public communicationTest(): Promise<WorkerAbilityTestReponse['CommunicationTest']> { |
||||
const mainThreadPostTime: WorkerAbilityTestPayload['CommunicationTest'] = Date.now(); |
||||
|
||||
return this.controller.requestPromise(WorkerAbilityTestActionType.CommunicationTest, mainThreadPostTime); |
||||
} |
||||
} |
@ -0,0 +1,13 @@
|
||||
import { WorkerAbilityTestMainThreadAction } from './action/action.worker_ability_test'; |
||||
|
||||
export class ${WorkerName}MainThreadWorker extends BI.Workers.MainThreadWorker { |
||||
private communicationTest: WorkerAbilityTestMainThreadAction; |
||||
|
||||
public initActions(): void { |
||||
this.communicationTest = this.createAction(WorkerAbilityTestMainThreadAction); |
||||
} |
||||
|
||||
public testCommunication() { |
||||
return this.communicationTest.communicationTest(); |
||||
} |
||||
} |
@ -0,0 +1,8 @@
|
||||
/* |
||||
* Worker 事务标识 |
||||
* 每类事务有命名空间, 包含多个具体事务 |
||||
*/ |
||||
|
||||
export const enum WorkerAbilityTestActionType { |
||||
CommunicationTest = 'CommunicationTest', |
||||
} |
@ -0,0 +1,13 @@
|
||||
/** |
||||
* 跨线程通信各事务的发送数据类型声明 |
||||
*/ |
||||
export interface WorkerAbilityTestPayload { |
||||
CommunicationTest: number; |
||||
} |
||||
|
||||
/** |
||||
* 跨线程通信各事务的响应数据类型声明 |
||||
*/ |
||||
export interface WorkerAbilityTestReponse { |
||||
CommunicationTest: number; |
||||
} |
@ -0,0 +1,24 @@
|
||||
import { WorkerAbilityTestActionType } from '../../utils/action_type'; |
||||
import { WorkerAbilityTestPayload, WorkerAbilityTestReponse } from '../../utils/payload_type'; |
||||
|
||||
export class WorkerAbilityTestWorkerThreadAction extends BI.Workers.WorkerBaseAction { |
||||
protected addActionHandler(): void { |
||||
this.controller.addActionHandler( |
||||
WorkerAbilityTestActionType.CommunicationTest, |
||||
this.communicationTest.bind(this) |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* 通信能力检测的处理器 |
||||
*/ |
||||
private communicationTest( |
||||
payload: WorkerAbilityTestPayload['CommunicationTest'] |
||||
): WorkerAbilityTestReponse['CommunicationTest'] { |
||||
const mainThreadPostTime = payload; |
||||
// 收到主线程信息的耗时 |
||||
const workerGetMessageDuration = Date.now() - mainThreadPostTime; |
||||
|
||||
return workerGetMessageDuration; |
||||
} |
||||
} |
@ -0,0 +1,12 @@
|
||||
// TODO: 这边需要先import fineui资源 |
||||
import { WorkerAbilityTestWorkerThreadAction } from './action/action.worker_ability_test'; |
||||
|
||||
class ${WorkerName}WorkerTreadWorker extends BI.Workers.WorkerThreadWorker { |
||||
public communicationTest: WorkerAbilityTestWorkerThreadAction; |
||||
|
||||
public initActions(): void { |
||||
this.communicationTest = this.createAction(WorkerAbilityTestWorkerThreadAction); |
||||
} |
||||
} |
||||
|
||||
export const ${workerName}WorkerTreadWorker = BI.Workers.createWorker(${WorkerName}WorkerTreadWorker); |
@ -1,7 +0,0 @@
|
||||
// import jQuery from "jquery";
|
||||
// import { _global } from "@/core/0.foundation";
|
||||
|
||||
// // todo:先垫着,不然开发会崩
|
||||
// _global.BI = _global.BI || {};
|
||||
|
||||
// _global.BI.jQuery = _global.BI.$ = jQuery;
|
@ -1,4 +1,3 @@
|
||||
import "./_jquery"; |
||||
import "./event"; |
||||
import "./fn"; |
||||
import "./jquery.mousewheel"; |
||||
|
@ -0,0 +1,81 @@
|
||||
/** |
||||
* 用于 jquery 在 worker 环境或者 V8 引擎的 polyfill |
||||
*/ |
||||
import { _global } from "@/core/0.foundation"; |
||||
if (!_global.window) { |
||||
_global.window = _global; |
||||
const document = (_global.document = {}); |
||||
const fakeElement = Object.create(document); |
||||
|
||||
Object.assign(document, { |
||||
parentNode: null, |
||||
nodeType: 9, |
||||
head: fakeElement, |
||||
body: fakeElement, |
||||
ownerDocument: document, |
||||
documentElement: document, |
||||
toString() { |
||||
return "FakeDocument"; |
||||
}, |
||||
appendChild(child) { |
||||
return child; |
||||
}, |
||||
implementation: { |
||||
createHTMLDocument() { |
||||
return { |
||||
body: { |
||||
childNodes: [], |
||||
}, |
||||
}; |
||||
}, |
||||
createDocumentFragment() { |
||||
return this; |
||||
}, |
||||
}, |
||||
getElementById() { |
||||
return fakeElement; |
||||
}, |
||||
createElement() { |
||||
return fakeElement; |
||||
}, |
||||
createDocumentFragment() { |
||||
return this; |
||||
}, |
||||
cloneNode() { |
||||
return this; |
||||
}, |
||||
getElementsByTagName() { |
||||
return [fakeElement]; |
||||
}, |
||||
getElementsByClassName() { |
||||
return [fakeElement]; |
||||
}, |
||||
setAttribute() { |
||||
return null; |
||||
}, |
||||
getAttribute() { |
||||
return null; |
||||
}, |
||||
removeChild() { |
||||
return null; |
||||
}, |
||||
addEventListener() { |
||||
return null; |
||||
}, |
||||
removeEventListener() { |
||||
return null; |
||||
}, |
||||
}); |
||||
|
||||
Object.assign(fakeElement, { |
||||
nodeType: 1, |
||||
style: {}, |
||||
ownerDocument: document, |
||||
parentNod: fakeElement, |
||||
firstChild: fakeElement, |
||||
lastChild: fakeElement, |
||||
toString() { |
||||
return "FakeElement"; |
||||
}, |
||||
}); |
||||
} |
Loading…
Reference in new issue