// import path from 'path'
import fs from 'fs'
import _ from 'lodash-es'
import w from './wsemip.umd.js'
// import rollupNodeWorker from './rollupNodeWorker.mjs'
// import rollupWebWorker from './rollupWebWorker.mjs'
import rollupWorkerCore from './rollupWorkerCore.mjs'
import rollupCode from './rollupCode.mjs'
function mergeCore(fpSrcNW, fpSrcWW) {
let c = `
import nw from '${fpSrcNW}'
import ww from '${fpSrcWW}'
function isWindow() {
return typeof window !== 'undefined' && typeof window.document !== 'undefined'
}
let wk
if(isWindow()){
wk = ww
}
else {
wk = nw
}
export default wk
`
return c
}
/**
* 使用rollup編譯檔案,並封裝至前端web worker與後端worker內
*
* @param {Object} opt 輸入設定物件
* @param {String} opt.name 輸入模組名稱字串,將來會掛於winodw下或於node引入使用
* @param {String} [opt.type='object'] 輸入模組類型字串,可選'function'、'object'。若使用'function',於初始化後可呼叫terminate銷毀;若使用'object',預設execObjectFunsByInstance為true,執行完指定函數後亦自動銷毀,若改execObjectFunsByInstance為false,就一樣得於初始化後呼叫terminate銷毀。回傳函數或物件。編譯後會掛載模組名稱至window下,若type使用'function'時則window['模組名稱']為函數,得自己初始化才能呼叫其內函數或監聽事件;若type使用'object'時則window['模組名稱']為物件,可直接呼叫其內函數預設'object'
* @param {Array} opt.funNames 輸入模組可被呼叫的函數名稱陣列
* @param {Array} [opt.evNames=[]] 輸入模組可監聽的函數名稱陣列,預設[]
* @param {String} opt.fpSrc 輸入原始碼檔案位置字串
* @param {String} opt.fpTar 輸入編譯完程式碼檔案儲存位置字串
* @param {String} [opt.nameDistType=''] 輸入編譯檔案名稱格式字串,可選'kebabCase',預設''
* @param {Function} [opt.hookNameDist=null] 輸入強制指定編譯檔案名稱函數,預設null,會複寫nameDistType之處理結果
* @param {String} [opt.formatOut='es'] 輸入欲編譯成js格式字串,可選'umd'、'iife'、'es',預設'es'
* @param {String} [opt.targets='new'] 輸入編譯等級字串,可選'new'、'old',預設'new'
* @param {Boolean} [opt.execFunctionByInstance=true] 輸入若模組類型為物件type='function'時,是否將function視為使用獨立實體執行並自動銷毀實體布林值,例如原模組就是一個運算函數,不需要回傳eventemmitter監聽事件,預設true
* @param {Boolean} [opt.execObjectFunsByInstance=true] 輸入若模組類型為物件type='object'時,各函式是否使用獨立實體執行布林值,例如使用到stream的各函式會因共用同一個實體導致降速,故各函數需自動有各自實體,預設true
* @param {Boolean} [opt.bNodePolyfill=false] 輸入當bNode為true時,編譯是否自動加入node polyfill布林值,主要把node專用語法(例如fs)轉為瀏覽器端語法,預設true
* @param {Boolean} [opt.bMinify=true] 輸入編譯檔案是否進行壓縮布林值,預設true
* @param {Boolean} [opt.keepFnames=false] 輸入當編譯檔案需壓縮時,是否保留函數名稱布林值,預設false
* @param {Array} [opt.mangleReserved=[]] 輸入當編譯檔案需壓縮時,需保留函數名稱或變數名稱布林值,預設[]
* @param {Boolean} [opt.bLog=true] 輸入是否顯示預設log布林值,預設true
*/
async function rollupWorker(opt = {}) {
//name
let name = _.get(opt, 'name', null)
if (!w.isestr(name)) {
return Promise.reject('invalid opt.name')
}
//fpSrc
let fpSrc = _.get(opt, 'fpSrc', null)
if (!w.fsIsFile(fpSrc)) {
return Promise.reject('opt.fpSrc is not file')
}
//fn
let fn = w.getFileName(fpSrc)
//fpTar
let fpTar = _.get(opt, 'fpTar', null)
if (!w.isestr(fpTar)) {
return Promise.reject('invalid opt.fpTar')
}
//nameDistType
let nameDistType = _.get(opt, 'nameDistType', null)
//nameDist
let nameDist = name
if (nameDistType === 'kebabCase') {
nameDist = _.kebabCase(name)
}
//hookNameDist
let hookNameDist = _.get(opt, 'hookNameDist', null)
if (_.isFunction(hookNameDist)) {
nameDist = hookNameDist(nameDist, name, fn)
}
//formatOut, umd為瀏覽器端直接使用, es為供vue-cli或webpack使用
let formatOut = _.get(opt, 'formatOut', null)
if (!formatOut) {
formatOut = 'es'
}
//targets
let targets = opt.targets
if (!w.isbol(targets)) {
targets = 'new' //於瀏覽器端,因程式碼用字串+blob方式作為web worker初始化之方式, 無法支援ie11(會需要改安全性)只好放棄, 且若被CSP檔那只能由伺服器改設定, 故此處直接改用最新語法new打包
}
//bMinify
let bMinify = _.get(opt, 'bMinify', null)
if (!w.isbol(bMinify)) {
bMinify = true
}
//bLog
let bLog = _.get(opt, 'bLog', null)
if (!w.isbol(bLog)) {
bLog = true
}
//console
if (bLog) {
console.log('transpiling: ' + w.getFileName(fpSrc))
}
//id
let id = w.genID()
let fpSrcNW = `./temp-${id}-nw.js`
let fpSrcWW = `./temp-${id}-ww.js`
let fpSrcMg = `./temp-${id}-mg.js`
async function core() {
//rollupWorkerCore for nodejs worker
let codeNW = await rollupWorkerCore({
...opt,
bNode: true,
bReturnCode: true,
bLog: false,
})
fs.writeFileSync(fpSrcNW, codeNW, 'utf8')
//rollupWorkerCore for web worker
let codeWW = await rollupWorkerCore({
...opt,
bNode: false,
bReturnCode: true,
bLog: false,
})
fs.writeFileSync(fpSrcWW, codeWW, 'utf8')
//mergeCore
let codeMerge = mergeCore(fpSrcNW, fpSrcWW)
fs.writeFileSync(fpSrcMg, codeMerge, 'utf8')
//rollupCode
let codeRes = await rollupCode(codeMerge, {
name: nameDist,
formatOut,
targets,
bNodePolyfill: false, //outer不需使用node polyfill
bMinify,
bBanner: false,
bSourcemap: false, //rollupCode不提供sourcemap
globals: { //因有已包含Nodejs與瀏覽器的worker封裝, 故需指定剔除Nodejs的worker的引用
'worker_threads': 'worker_threads',
},
external: [
'worker_threads',
],
bLog: false,
})
//writeFileSync
fs.writeFileSync(fpTar, codeRes, 'utf8')
//console
if (bLog) {
console.log('\x1b[32m%s\x1b[0m', 'output: ' + w.getFileName(fpTar))
}
}
//core
await core()
.catch((err) => {
console.log(err)
})
.finally(() => {
//unlinkSync, 不論編譯成功失敗都刪除檔案
try {
fs.unlinkSync(fpSrcNW)
}
catch (err) {
console.log(err)
}
try {
fs.unlinkSync(fpSrcWW)
}
catch (err) {
console.log(err)
}
try {
fs.unlinkSync(fpSrcMg)
}
catch (err) {
console.log(err)
}
})
}
export default rollupWorker