組態檔中的loader設定
可以根據組態檔匹配到到規則,去執行相應的loader。
// analyze.config.js // 引入loader const jsLoader = require('./lib/jsLoader') const jsonLoader = require('./lib/jsonLoader') const cssLoader = require('./lib/cssLoader') const htmlLoader = require('./lib/htmlLoader') const signLoader = require('./lib/signLoader') const config = { entry: './', output: { name: 'dist', src: './' }, module: [ { test: /\.js$/, loader: [signLoader, jsLoader], }, { test: /\.wxss$/, loader: [cssLoader], outputPath: (outputPath) => outputPath.replace('.wxss', '.acss') }, { test: /\.wxml$/, loader: [htmlLoader], outputPath: (outputPath) => outputPath.replace('.wxml', '.axml') }, { test: /\.json$/, loader: [jsonLoader], }, ] } module.exports = config
具體loader實現
以jsLoader為例子,接收原始碼作為引數,返回編譯後獲得的新的原始碼
// 前幾篇中封裝的js轉換器 const JsParser = require('./JsParser') function loader(source) { const jsParser = new JsParser() let ast = jsParser.parse(source) ast = jsParser.astConverter(ast) return jsParser.astToCode(ast) } module.exports = loader
不同檔案選擇對應loader
// 重寫Analyze函數中的analyzeFileToLoard檔案分析部分 function Analyze(filePath, outputPath){ if (fs.statSync(filePath).isDirectory()) { const files = fs.readdirSync(filePath) files.forEach(file => { const currentFilePath = filePath+'/'+file const currentOutputPath = outputPath+'/'+file if(fs.statSync(currentFilePath).isDirectory()) { fs.mkdirSync(currentOutputPath) Analyze(currentFilePath, currentOutputPath) } else analyzeFileToLoard(currentFilePath, currentOutputPath) }) } else analyzeFileToLoard(filePath, outputPath) }
function analyzeFileToLoard(inputPath, outputPath) { let source = readFile(inputPath) // 讀取原始碼 const loaders = config.module loaders.forEach(loader => { // 遍歷組態檔,看是否有匹配檔案的loader規則 if (loader.test.test(inputPath)) { // 使用loader source = useLoader(source, loader.loader, outputPath) // 輸出路徑處理常式 if (loader.outputPath) outputPath = loader.outputPath(outputPath) } }) writeFile(outputAppPath(outputPath), source) // 將處理過後的原始碼寫入檔案 }
loader過濾和執行
loader執行是個逆序的執行,從右邊向左依次執行。在這裡我們先用同步的loader來做討論。
loader執行前還有個pitch階段,感覺pitch這個起名方式並不是特別合適,我更願意叫它過濾篩選階段。先去順序執行loader上的pitch方法,要是pitch有返回值,就不再執行在該loader之前執行的loader。
function useLoader(source, loaders = []) { // 執行loader儲存列表 const loaderList = [] // 遞回去篩選需要執行的loader function loaderFilter(loaders) { const [firstLoader, ...ortherLoader] = loaders if (loaders.length === 0) return // 執行pitch,並將剩餘的loader傳入作為引數 if (firstLoader.pitch && firstLoader.pitch(ortherLoader)) return ortherLoader else { // 將可用loader加入待執行列表 loaderList.push(firstLoader) // 剩餘loader作為引數 遞迴呼叫 loaderFilter(ortherLoader) } } // 大概,暫時用不到。。。 const remainLoader = loaderFilter(loaders) // 同步loader逆序執行 function runLoader(source, loaderList) { const loader = loaderList.pop() let newSource = loader(source) if (loaderList.length > 0) return runLoader(newSource, loaderList) else return newSource } source = runLoader(source, loaderList) return source }
實驗
寫個signLoader,看看loader能不能像我們想的那樣逆序執行
function loader(source) { let sign = `/** * @Author: LY */ ` source = sign + source return source } module.exports = loader
結果:
這樣簡易的loader部分算是完成了,但這麼寫只能執行一些同步的loader,非同步的loader無法等待執行完成後再寫入。
相關學習推薦:
以上就是微信小程式轉換器之 loader設計實現的詳細內容,更多請關注TW511.COM其它相關文章!