forked from fanruan/fineui
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 "./event"; |
||||||
import "./fn"; |
import "./fn"; |
||||||
import "./jquery.mousewheel"; |
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