-
Notifications
You must be signed in to change notification settings - Fork 4.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
…closes #5433
- Loading branch information
Showing
9 changed files
with
293 additions
and
348 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import * as path from 'path' | ||
import * as qs from 'querystring' | ||
|
||
import { stringifyRequest, getOptions } from 'loader-utils' | ||
import { MINI_APP_FILES, NODE_MODULES_REG, NODE_MODULES } from '../utils/constants' | ||
|
||
const isPitcher = l => l.path !== __filename | ||
const isPreLoader = l => !l.pitchExecuted | ||
const isPostLoader = l => l.pitchExecuted | ||
|
||
export default code => code | ||
|
||
const genRequest = (loaderRequest, loaders) => { | ||
const seen = new Map() | ||
const loaderStrings: string[] = [] | ||
loaders.forEach(loader => { | ||
const identifier = typeof loader === 'string' | ||
? loader | ||
: (loader.path + loader.query) | ||
const request = typeof loader === 'string' ? loader : loader.request | ||
if (!seen.has(identifier)) { | ||
seen.set(identifier, true) | ||
loaderStrings.push(request) | ||
} | ||
}) | ||
|
||
return stringifyRequest(loaderRequest, '-!' + [ | ||
...loaderStrings, | ||
loaderRequest.resourcePath + loaderRequest.resourceQuery | ||
].join('!')) | ||
} | ||
|
||
export function pitch () { | ||
const { sourceDir, buildAdapter } = getOptions(this) | ||
const query = qs.parse(this.resourceQuery.slice(1)) | ||
|
||
let loaders = this.loaders | ||
loaders = loaders.filter(isPitcher) | ||
if (query.type === 'template') { | ||
const preLoaders = loaders.filter(isPreLoader) | ||
const postLoaders = loaders.filter(isPostLoader) | ||
let fileLoaderRequest = `file-loader?name=[path][name]${MINI_APP_FILES[buildAdapter].TEMPL}` | ||
if (NODE_MODULES_REG.test(this.resourcePath)) { | ||
const baseContext = path.join(process.cwd(), NODE_MODULES) | ||
fileLoaderRequest += `&context=${baseContext}&outputPath=npm` | ||
} else { | ||
fileLoaderRequest += `&context=${sourceDir}` | ||
} | ||
const request = genRequest(this, [ | ||
...postLoaders, | ||
fileLoaderRequest, | ||
require.resolve('./miniTemplateLoader'), | ||
...preLoaders | ||
]) | ||
return `export * from ${request}` | ||
} | ||
const request = genRequest(this, loaders) | ||
return `import mod from ${request}; export default mod; export * from ${request}` | ||
} |
138 changes: 130 additions & 8 deletions
138
packages/taro-mini-runner/src/loaders/wxTransformerLoader.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,25 +1,147 @@ | ||
import { getOptions } from 'loader-utils' | ||
import * as qs from 'querystring' | ||
import * as path from 'path' | ||
|
||
import { getOptions, stringifyRequest } from 'loader-utils' | ||
import wxTransformer from '@tarojs/transformer-wx' | ||
import { transform, transformFromAst } from 'babel-core' | ||
import * as t from 'babel-types' | ||
import generate from 'better-babel-generator' | ||
|
||
import { | ||
REG_TYPESCRIPT, | ||
PARSE_AST_TYPE, | ||
NODE_MODULES_REG, | ||
BUILD_TYPES | ||
} from '../utils/constants' | ||
import processAst from '../utils/processAst' | ||
import { npmCodeHack, isEmptyObject } from '../utils' | ||
import parseAst from '../utils/parseAst' | ||
|
||
import { REG_TYPESCRIPT } from '../utils/constants' | ||
const cannotRemoves = ['@tarojs/taro', 'react', 'nervjs'] | ||
|
||
const cachedResults = new Map() | ||
|
||
export default function wxTransformerLoader (source) { | ||
const { buildAdapter } = getOptions(this) | ||
const { | ||
babel: babelConfig, | ||
alias, | ||
buildAdapter, | ||
designWidth, | ||
deviceRatio, | ||
sourceDir | ||
} = getOptions(this) | ||
const filePath = this.resourcePath | ||
const { resourceQuery } = this | ||
const rawQuery = resourceQuery.slice(1) | ||
const inheritQuery = `&${rawQuery}` | ||
const incomingQuery = qs.parse(rawQuery) | ||
const isQuickApp = buildAdapter === BUILD_TYPES.QUICKAPP | ||
try { | ||
const stringifyRequestFn = r => stringifyRequest(this, r) | ||
const miniType = (incomingQuery.parse ? incomingQuery.parse : this._module.miniType) || PARSE_AST_TYPE.NORMAL | ||
const rootProps: { [key: string]: any } = {} | ||
if (isQuickApp && miniType === PARSE_AST_TYPE.PAGE) { | ||
// 如果是快应用,需要提前解析一次 ast,获取 config | ||
const aheadTransformResult = wxTransformer({ | ||
code: source, | ||
sourcePath: filePath, | ||
sourceDir, | ||
isRoot: miniType === PARSE_AST_TYPE.PAGE, | ||
isTyped: REG_TYPESCRIPT.test(filePath), | ||
adapter: buildAdapter | ||
}) | ||
const res = parseAst(aheadTransformResult.ast, buildAdapter) | ||
const appConfig = this._compiler.appConfig | ||
if (res.configObj.enablePullDownRefresh || (appConfig.window && appConfig.window.enablePullDownRefresh)) { | ||
rootProps.enablePullDownRefresh = true | ||
} | ||
if (appConfig.tabBar) { | ||
rootProps.tabBar = appConfig.tabBar | ||
} | ||
rootProps.pagePath = filePath.replace(sourceDir, '').replace(path.extname(filePath), '') | ||
if (res.hasEnablePageScroll) { | ||
rootProps.enablePageScroll = true | ||
} | ||
} | ||
const wxTransformerParams: any = { | ||
code: source, | ||
sourceDir: sourceDir, | ||
sourcePath: filePath, | ||
isTyped: REG_TYPESCRIPT.test(filePath), | ||
adapter: buildAdapter, | ||
isNormal: true | ||
rootProps: isEmptyObject(rootProps) || rootProps | ||
} | ||
if (miniType === PARSE_AST_TYPE.ENTRY) { | ||
wxTransformerParams.isApp = true | ||
} else if (miniType === PARSE_AST_TYPE.PAGE) { | ||
wxTransformerParams.isRoot = true | ||
} else if (miniType === PARSE_AST_TYPE.NORMAL) { | ||
wxTransformerParams.isNormal = true | ||
} | ||
let template, transCode | ||
if (!incomingQuery.parse) { | ||
const transformResult = wxTransformer(wxTransformerParams) | ||
const ast = transformResult.ast | ||
template = transformResult.template | ||
const newAst = transformFromAst(ast, '', { | ||
plugins: [ | ||
[require('babel-plugin-preval')], | ||
[require('babel-plugin-danger-remove-unused-import'), { ignore: cannotRemoves }] | ||
] | ||
}).ast as t.File | ||
const result = processAst({ | ||
ast: newAst, | ||
buildAdapter, | ||
type: miniType, | ||
designWidth, | ||
deviceRatio, | ||
sourceFilePath: filePath, | ||
sourceDir, | ||
alias | ||
}) | ||
const code = generate(result).code | ||
const res = transform(code, babelConfig) | ||
if (NODE_MODULES_REG.test(filePath) && res.code) { | ||
res.code = npmCodeHack(filePath, res.code, buildAdapter) | ||
} | ||
transCode = res.code | ||
cachedResults.set(filePath, { | ||
template, | ||
transCode | ||
}) | ||
} else { | ||
const cache = cachedResults.get(filePath) | ||
template = cache.template | ||
transCode = cache.transCode | ||
} | ||
|
||
let resultCode = '' | ||
if (miniType === PARSE_AST_TYPE.ENTRY || miniType === PARSE_AST_TYPE.PAGE || miniType === PARSE_AST_TYPE.COMPONENT) { | ||
if (incomingQuery.type === 'template') { | ||
return this.callback(null, template) | ||
} | ||
if (incomingQuery.type === 'script') { | ||
return this.callback(null, transCode) | ||
} | ||
if (template && template.length) { | ||
const query = `?taro&type=template&parse=${miniType}${inheritQuery}` | ||
const templateImport = `import { template } from ${stringifyRequestFn(filePath + query)};\n` | ||
resultCode += templateImport | ||
} | ||
const scriptQuery = `?taro&type=script&parse=${miniType}${inheritQuery}` | ||
const scriptRequest = stringifyRequestFn(filePath + scriptQuery) | ||
const scriptImport = ( | ||
`import script from ${scriptRequest}\n` + | ||
`export * from ${scriptRequest}` // support named exports | ||
) | ||
resultCode += scriptImport | ||
return resultCode | ||
} | ||
const transformResult = wxTransformer(wxTransformerParams) | ||
this.callback(null, transformResult.code, transformResult.ast) | ||
return transformResult.code | ||
return transCode | ||
} catch (error) { | ||
console.log(error) | ||
this.emitError(error) | ||
this.callback(null, source, null) | ||
this.callback(null, source) | ||
return source | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import * as qs from 'querystring' | ||
|
||
import * as RuleSet from 'webpack/lib/RuleSet' | ||
|
||
import { BUILD_TYPES } from '../utils/constants' | ||
|
||
const PLUGIN_NAME = 'MiniLoaderPlugin' | ||
const NS = 'TARO' | ||
|
||
interface IOptions { | ||
sourceDir: string, | ||
buildAdapter: BUILD_TYPES | ||
} | ||
|
||
export default class MiniLoaderPlugin { | ||
options: IOptions | ||
constructor (options) { | ||
this.options = options | ||
} | ||
|
||
apply (compiler) { | ||
const { | ||
sourceDir, | ||
buildAdapter | ||
} = this.options | ||
compiler.hooks.compilation.tap(PLUGIN_NAME, compilation => { | ||
const normalModuleLoader = compilation.hooks.normalModuleLoader | ||
normalModuleLoader.tap(PLUGIN_NAME, loaderContext => { | ||
loaderContext[NS] = true | ||
}) | ||
}) | ||
const rawRules = compiler.options.module.rules | ||
const { rules } = new RuleSet(rawRules) | ||
|
||
const pitcher = { | ||
loader: require.resolve('../loaders/pitcher'), | ||
resourceQuery: query => { | ||
const parsed = qs.parse(query.slice(1)) | ||
return parsed.taro != null | ||
}, | ||
options: { | ||
sourceDir, | ||
buildAdapter | ||
} | ||
} | ||
compiler.options.module.rules = [ | ||
pitcher, | ||
...rules | ||
] | ||
} | ||
} |
Oops, something went wrong.