diff --git a/packages/taro-mini-runner/src/loaders/pitcher.ts b/packages/taro-mini-runner/src/loaders/pitcher.ts new file mode 100644 index 000000000000..1175d1095d11 --- /dev/null +++ b/packages/taro-mini-runner/src/loaders/pitcher.ts @@ -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}` +} diff --git a/packages/taro-mini-runner/src/loaders/wxTransformerLoader.ts b/packages/taro-mini-runner/src/loaders/wxTransformerLoader.ts index 63c106f37c58..6a2ec63c1a3b 100644 --- a/packages/taro-mini-runner/src/loaders/wxTransformerLoader.ts +++ b/packages/taro-mini-runner/src/loaders/wxTransformerLoader.ts @@ -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 } } diff --git a/packages/taro-mini-runner/src/plugins/MiniLoaderPlugin.ts b/packages/taro-mini-runner/src/plugins/MiniLoaderPlugin.ts new file mode 100644 index 000000000000..d6d4287b5924 --- /dev/null +++ b/packages/taro-mini-runner/src/plugins/MiniLoaderPlugin.ts @@ -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 + ] + } +} diff --git a/packages/taro-mini-runner/src/plugins/MiniPlugin.ts b/packages/taro-mini-runner/src/plugins/MiniPlugin.ts index e144d1720b25..2aed328d25da 100644 --- a/packages/taro-mini-runner/src/plugins/MiniPlugin.ts +++ b/packages/taro-mini-runner/src/plugins/MiniPlugin.ts @@ -25,7 +25,7 @@ import rewriterTemplate from '../quickapp/template-rewriter' import TaroLoadChunksPlugin from './TaroLoadChunksPlugin' import TaroNormalModulesPlugin from './TaroNormalModulesPlugin' -import VirtualModulePlugin from './VirtualModulePlugin/VirtualModulePlugin' +import MiniLoaderPlugin from './MiniLoaderPlugin' interface IMiniPluginOptions { appEntry?: string, @@ -153,6 +153,8 @@ export default class MiniPlugin { changedFileType: PARSE_AST_TYPE | undefined addedComponents: Set pageComponentsDependenciesMap: Map> + dependencies: Map + quickappImports: Map> constructor (options = {}) { this.options = defaults(options || {}, { @@ -177,6 +179,8 @@ export default class MiniPlugin { this.errors = [] this.addedComponents = new Set() this.pageComponentsDependenciesMap = new Map() + this.dependencies = new Map() + this.quickappImports = new Map() } tryAsync = fn => async (arg, callback) => { @@ -228,6 +232,17 @@ export default class MiniPlugin { }) ) + compiler.hooks.make.tapAsync(PLUGIN_NAME, (compilation: webpack.compilation.Compilation, callback) => { + const dependencies = this.dependencies + const promises: any[] = [] + dependencies.forEach(dep => { + promises.push(new Promise((resolve, reject) => { + compilation.addEntry(this.sourceDir, dep, dep.name, err => err ? reject(err) : resolve()) + })) + }) + Promise.all(promises).then(() => callback(), callback) + }) + compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation, { normalModuleFactory }) => { compilation.dependencyFactories.set(SingleEntryDependency, normalModuleFactory) compilation.dependencyFactories.set(TaroSingleEntryDependency, normalModuleFactory) @@ -267,6 +282,10 @@ export default class MiniPlugin { ) new TaroNormalModulesPlugin().apply(compiler) + new MiniLoaderPlugin({ + buildAdapter: this.options.buildAdapter, + sourceDir: this.sourceDir + }).apply(compiler) } getChangedFiles (compiler) { @@ -487,7 +506,7 @@ export default class MiniPlugin { return filePath.replace(this.context, '').replace(/\\/g, '/').replace(/^\//, '') } - getPages (compiler: webpack.Compiler) { + getPages (compiler) { const { buildAdapter } = this.options const appEntry = this.appEntry const code = fs.readFileSync(appEntry).toString() @@ -503,6 +522,7 @@ export default class MiniPlugin { const { configObj } = parseAst(transformResult.ast, buildAdapter) const appPages = configObj.pages this.appConfig = configObj + compiler.appConfig = configObj if (!appPages || appPages.length === 0) { throw new Error('缺少页面') } @@ -511,11 +531,9 @@ export default class MiniPlugin { } this.getSubPackages(configObj) this.getTabBarFiles(compiler, configObj) - const template = '' taroFileTypeMap[this.appEntry] = { type: PARSE_AST_TYPE.ENTRY, config: configObj, - template, code: transformResult.code } this.pages = new Set([ @@ -656,7 +674,6 @@ export default class MiniPlugin { let configObj let taroSelfComponents let depComponents - let template let code = fs.readFileSync(file.path).toString() if (isNative) { const configPath = this.getConfigPath(file.path) @@ -669,28 +686,7 @@ export default class MiniPlugin { })) : [] } } else { - const rootProps: { [key: string]: any } = {} if (isQuickApp && isRoot) { - // 如果是快应用,需要提前解析一次 ast,获取 config - const aheadTransformResult = wxTransformer({ - code, - sourcePath: file.path, - sourceDir: this.sourceDir, - isRoot, - isTyped: REG_TYPESCRIPT.test(file.path), - adapter: buildAdapter - }) - const res = parseAst(aheadTransformResult.ast, buildAdapter) - if (res.configObj.enablePullDownRefresh || (this.appConfig.window && this.appConfig.window.enablePullDownRefresh)) { - rootProps.enablePullDownRefresh = true - } - if (this.appConfig.tabBar) { - rootProps.tabBar = this.appConfig.tabBar - } - rootProps.pagePath = file.path.replace(this.sourceDir, '').replace(path.extname(file.path), '') - if (res.hasEnablePageScroll) { - rootProps.enablePageScroll = true - } const styleName = this.getStylePath(quickappCommonStyle) const taroJsQuickAppStylesPath = path.resolve(this.options.nodeModulesPath, taroJsQuickAppComponents, 'src/common/css') const sourceStylePath = path.resolve(taroJsQuickAppStylesPath, styleName) @@ -705,7 +701,6 @@ export default class MiniPlugin { sourceDir: this.sourceDir, isTyped: REG_TYPESCRIPT.test(file.path), isRoot, - rootProps: isEmptyObject(rootProps) || rootProps, adapter: buildAdapter }) let parseAstRes = parseAst(transformResult.ast, buildAdapter) @@ -728,7 +723,6 @@ export default class MiniPlugin { taroSelfComponents.add('taro-page') } depComponents = transformResult.components - template = transformResult.template code = transformResult.code } depComponents = depComponents.filter(item => !/^plugin:\/\//.test(item.path)) @@ -748,10 +742,7 @@ export default class MiniPlugin { } })) } - template = generateQuickAppUx({ - template, - imports: new Set([...importTaroSelfComponents, ...importUsingComponent, ...importCustomComponents]) - }) + this.quickappImports.set(scriptPath, new Set([...importTaroSelfComponents, ...importUsingComponent, ...importCustomComponents])) } if (!this.isWatch) { printLog(processTypeEnum.COMPILE, isRoot ? '发现页面' : '发现组件', this.getShowPath(file.path)) @@ -759,7 +750,6 @@ export default class MiniPlugin { taroFileTypeMap[file.path] = { type: isRoot ? PARSE_AST_TYPE.PAGE : PARSE_AST_TYPE.COMPONENT, config: merge({}, isComponentConfig, buildUsingComponents(file.path, this.sourceDir, alias, depComponents), configObj), - template, code } if (isQuickApp && taroSelfComponents) { @@ -806,10 +796,17 @@ export default class MiniPlugin { } addEntry (compiler: webpack.Compiler, entryPath, entryName, entryType) { - compiler.hooks.make.tapAsync(PLUGIN_NAME, (compilation: webpack.compilation.Compilation, callback) => { - const dep = new TaroSingleEntryDependency(entryPath, entryName, { name: entryName }, entryType) - compilation.addEntry(this.sourceDir, dep, entryName, callback) - }) + let dep + if (this.dependencies.has(entryPath)) { + dep = this.dependencies.get(entryPath) + dep.name = entryName + dep.loc = { name: entryName } + dep.entryPath = entryPath + dep.entryType = entryType + } else { + dep = new TaroSingleEntryDependency(entryPath, entryName, { name: entryName }, entryType) + } + this.dependencies.set(entryPath, dep) } addEntries (compiler: webpack.Compiler) { @@ -848,12 +845,11 @@ export default class MiniPlugin { Object.keys(taroFileTypeMap).forEach(item => { const relativePath = this.getRelativePath(item) const extname = path.extname(item) - const templatePath = relativePath.replace(extname, MINI_APP_FILES[buildAdapter].TEMPL).replace(/\\/g, '/') - const jsonPath = relativePath.replace(extname, MINI_APP_FILES[buildAdapter].CONFIG).replace(/\\/g, '/') - const scriptPath = relativePath.replace(extname, MINI_APP_FILES[buildAdapter].SCRIPT).replace(/\\/g, '/') - const stylePath = relativePath.replace(extname, MINI_APP_FILES[buildAdapter].STYLE).replace(/\\/g, '/') + const jsonPath = relativePath.replace(extname, MINI_APP_FILES[buildAdapter].CONFIG).replace(/\\/g, '/').replace(/^\//, '') + const scriptPath = relativePath.replace(extname, MINI_APP_FILES[buildAdapter].SCRIPT).replace(/\\/g, '/').replace(/^\//, '') + const templatePath = relativePath.replace(extname, MINI_APP_FILES[buildAdapter].TEMPL).replace(/\\/g, '/').replace(/^\//, '') + const stylePath = relativePath.replace(extname, MINI_APP_FILES[buildAdapter].STYLE).replace(/\\/g, '/').replace(/^\//, '') const itemInfo = taroFileTypeMap[item] - let template = itemInfo.template if (!isQuickApp) { const jsonStr = JSON.stringify(itemInfo.config) compilation.assets[jsonPath] = { @@ -862,6 +858,11 @@ export default class MiniPlugin { } } else { let hitScriptItem + let template = compilation.assets[templatePath] + template = generateQuickAppUx({ + template: template ? (template._source ? template._source.source() : template._value) : '', + imports: this.quickappImports.get(item) + }) template = template ? rewriterTemplate(template) : template Object.keys(compilation.assets).forEach(item => { if (stylePath.indexOf(item) >= 0) { @@ -890,14 +891,8 @@ export default class MiniPlugin { size: () => quickappJSONStr.length, source: () => quickappJSONStr } - } - if (template && ( - !this.changedFile - || this.changedFile === item - || this.changedFileType === PARSE_AST_TYPE.ENTRY - || Array.from(this.addedComponents).some(component => component.path === item))) { compilation.assets[templatePath] = { - size: () => template!.length, + size: () => template.length, source: () => template } } @@ -958,18 +953,6 @@ export default class MiniPlugin { }) } - transferFileContent (compiler: webpack.Compiler) { - Object.keys(taroFileTypeMap).forEach(item => { - const itemInfo = taroFileTypeMap[item] - if (typeof itemInfo.code === 'string') { - new VirtualModulePlugin({ - path: item, - contents: itemInfo.code - }).apply(compiler) - } - }) - } - judgeFileToBeTaroComponent ( code: string, sourcePath: string, @@ -1002,7 +985,6 @@ export default class MiniPlugin { } else { this.getPluginFiles(compiler) } - this.transferFileContent(compiler) } watchRun (compiler: webpack.Compiler, changedFiles: string[]) { @@ -1062,7 +1044,6 @@ export default class MiniPlugin { } else { this.getPluginFiles(compiler) } - this.transferFileContent(compiler) } if (obj && type === PARSE_AST_TYPE.COMPONENT && !Array.from(this.components).some(item => item.path === obj.path)) { diff --git a/packages/taro-mini-runner/src/plugins/TaroLoadChunksPlugin.ts b/packages/taro-mini-runner/src/plugins/TaroLoadChunksPlugin.ts index 8b50a5f4a6ff..bd0d46e23fd2 100644 --- a/packages/taro-mini-runner/src/plugins/TaroLoadChunksPlugin.ts +++ b/packages/taro-mini-runner/src/plugins/TaroLoadChunksPlugin.ts @@ -1,6 +1,6 @@ import * as path from 'path' -import webpack, { compilation } from 'webpack' +import webpack from 'webpack' import { ConcatSource } from 'webpack-sources' import { urlToRequest } from 'loader-utils' diff --git a/packages/taro-mini-runner/src/plugins/VirtualModulePlugin/VirtualModulePlugin.ts b/packages/taro-mini-runner/src/plugins/VirtualModulePlugin/VirtualModulePlugin.ts deleted file mode 100644 index 45900d8a2423..000000000000 --- a/packages/taro-mini-runner/src/plugins/VirtualModulePlugin/VirtualModulePlugin.ts +++ /dev/null @@ -1,127 +0,0 @@ -import * as path from 'path' -import VirtualStats from './virtualStats' -import webpack from 'webpack' - -export default class VirtualModulePlugin { - options: { - moduleName: string - contents: any - path?: string - } - constructor (options) { - this.options = options - } - - apply (compiler: webpack.Compiler) { - const moduleName = this.options.moduleName - const ctime = VirtualModulePlugin.statsDate() - let modulePath = this.options.path - - let contents - if (typeof this.options.contents === 'string') { - contents = this.options.contents - } - if (typeof this.options.contents === 'object') { - if (typeof this.options.contents.then !== 'function') { - contents = JSON.stringify(this.options.contents) - } - } - if (typeof this.options.contents === 'function') { - contents = this.options.contents() - } - if (typeof contents === 'string') { - contents = Promise.resolve(contents) - } - - function resolverPlugin(request, cb) { - // populate the file system cache with the virtual module - const fs = (this && this.fileSystem) || compiler.inputFileSystem - const join = (this && this.join) || path.join - - if (typeof request === 'string') { - request = cb - cb = null - } - - if (!modulePath) { - modulePath = join(compiler.context, moduleName) - } - - const resolve = (data) => { - VirtualModulePlugin.populateFilesystem({ fs, modulePath, contents: data, ctime }) - } - - const resolved = contents.then(resolve) - if (!cb) { - return - } - - resolved.then(() => cb()) - } - - compiler.hooks.normalModuleFactory.tap('VirtualModulePlugin', (nmf) => { - nmf.hooks.beforeResolve.tap('VirtualModulePlugin', resolverPlugin) - }) - } - - static populateFilesystem (options) { - const fs = options.fs - const modulePath = options.modulePath - const contents = options.contents - const mapIsAvailable = typeof Map !== 'undefined' - const statStorageIsMap = mapIsAvailable && fs._statStorage.data instanceof Map - const readFileStorageIsMap = mapIsAvailable && fs._readFileStorage.data instanceof Map - - const stats = VirtualModulePlugin.createStats(options) - if (statStorageIsMap) { // enhanced-resolve@3.4.0 or greater - fs._statStorage.data.set(modulePath, [null, stats]) - } else { // enhanced-resolve@3.3.0 or lower - fs._statStorage.data[modulePath] = [null, stats] - } - if (readFileStorageIsMap) { // enhanced-resolve@3.4.0 or greater - fs._readFileStorage.data.set(modulePath, [null, contents]) - } else { // enhanced-resolve@3.3.0 or lower - fs._readFileStorage.data[modulePath] = [null, contents] - } - } - - static statsDate (inputDate?) { - if (!inputDate) { - inputDate = new Date() - } - return inputDate.toString() - } - - static createStats(options) { - if (!options) { - options = {} - } - if (!options.ctime) { - options.ctime = VirtualModulePlugin.statsDate() - } - if (!options.mtime) { - options.mtime = VirtualModulePlugin.statsDate() - } - if (!options.size) { - options.size = 0 - } - if (!options.size && options.contents) { - options.size = options.contents.length - } - return new VirtualStats({ - dev: 8675309, - nlink: 1, - uid: 501, - gid: 20, - rdev: 0, - blksize: 4096, - ino: 44700000, - mode: 33188, - size: options.size, - atime: options.mtime, - mtime: options.mtime, - ctime: options.ctime, - birthtime: options.ctime, - }) - } -} diff --git a/packages/taro-mini-runner/src/plugins/VirtualModulePlugin/virtualStats.ts b/packages/taro-mini-runner/src/plugins/VirtualModulePlugin/virtualStats.ts deleted file mode 100644 index 459dbbfa74b0..000000000000 --- a/packages/taro-mini-runner/src/plugins/VirtualModulePlugin/virtualStats.ts +++ /dev/null @@ -1,92 +0,0 @@ -/** - * Used to cache a stats object for the virtual file. - * Extracted from the `mock-fs` package. - * - * @author Tim Schaub http://tschaub.net/ - * @link https://github.com/tschaub/mock-fs/blob/master/lib/binding.js - * @link https://github.com/tschaub/mock-fs/blob/master/license.md - */ - -import * as constants from 'constants' - -export default class VirtualStats { - mode: number - /** - * Create a new stats object. - * @param {Object} config Stats properties. - * @constructor - */ - constructor (config) { - for (const key in config) { - if (!config.hasOwnProperty(key)) { - continue - } - this[key] = config[key] - } - } - - /** - * Check if mode indicates property. - * @param {number} property Property to check. - * @return {boolean} Property matches mode. - */ - _checkModeProperty(property) { - return ((this.mode & constants.S_IFMT) === property) - } - - - /** - * @return {Boolean} Is a directory. - */ - isDirectory() { - return this._checkModeProperty(constants.S_IFDIR) - } - - - /** - * @return {Boolean} Is a regular file. - */ - isFile() { - return this._checkModeProperty(constants.S_IFREG) - } - - - /** - * @return {Boolean} Is a block device. - */ - isBlockDevice() { - return this._checkModeProperty(constants.S_IFBLK) - } - - - /** - * @return {Boolean} Is a character device. - */ - isCharacterDevice() { - return this._checkModeProperty(constants.S_IFCHR) - } - - - /** - * @return {Boolean} Is a symbolic link. - */ - isSymbolicLink() { - return this._checkModeProperty(constants.S_IFLNK) - } - - - /** - * @return {Boolean} Is a named pipe. - */ - isFIFO() { - return this._checkModeProperty(constants.S_IFIFO) - } - - - /** - * @return {Boolean} Is a socket. - */ - isSocket() { - return this._checkModeProperty(constants.S_IFSOCK) - } -} diff --git a/packages/taro-mini-runner/src/loaders/fileParseLoader.ts b/packages/taro-mini-runner/src/utils/processAst.ts similarity index 94% rename from packages/taro-mini-runner/src/loaders/fileParseLoader.ts rename to packages/taro-mini-runner/src/utils/processAst.ts index 3e2e8204d090..919087abf4cc 100644 --- a/packages/taro-mini-runner/src/loaders/fileParseLoader.ts +++ b/packages/taro-mini-runner/src/utils/processAst.ts @@ -1,10 +1,7 @@ import * as path from 'path' import * as fs from 'fs-extra' -import { getOptions } from 'loader-utils' -import { transform, transformFromAst } from 'babel-core' import * as t from 'babel-types' -import generate from 'better-babel-generator' import traverse, { NodePath } from 'babel-traverse' import * as _ from 'lodash' @@ -16,25 +13,21 @@ import { QUICKAPP_SPECIAL_COMPONENTS, PARSE_AST_TYPE, excludeReplaceTaroFrameworkPkgs, - REG_SCRIPTS, - NODE_MODULES_REG -} from '../utils/constants' + REG_SCRIPTS +} from './constants' import { isNpmPkg, isQuickAppPkg, isAliasPath, replaceAliasPath, resolveScriptPath, - promoteRelativePath, - npmCodeHack -} from '../utils' -import { convertSourceStringToAstExpression } from '../utils/astConvert' + promoteRelativePath +} from '.' +import { convertSourceStringToAstExpression } from './astConvert' import babylonConfig from '../config/babylon' const template = require('babel-template') -const cannotRemoves = ['@tarojs/taro', 'react', 'nervjs'] - const NON_WEBPACK_REQUIRE = '__non_webpack_require__' interface IProcessAstArgs { @@ -48,7 +41,7 @@ interface IProcessAstArgs { alias: object } -function processAst ({ +export default function processAst ({ ast, buildAdapter, type, @@ -614,38 +607,3 @@ function processAst ({ return ast } - -export default function fileParseLoader (source, ast) { - const { - babel: babelConfig, - alias, - buildAdapter, - designWidth, - deviceRatio, - sourceDir - } = getOptions(this) - const filePath = this.resourcePath - const newAst = transformFromAst(ast, '', { - plugins: [ - [require('babel-plugin-preval')], - [require('babel-plugin-danger-remove-unused-import'), { ignore: cannotRemoves }] - ] - }).ast as t.File - const miniType = this._module.miniType || PARSE_AST_TYPE.NORMAL - 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) - } - return res.code -} diff --git a/packages/taro-mini-runner/src/webpack/chain.ts b/packages/taro-mini-runner/src/webpack/chain.ts index 90f43fddb937..5ab6c463e484 100644 --- a/packages/taro-mini-runner/src/webpack/chain.ts +++ b/packages/taro-mini-runner/src/webpack/chain.ts @@ -76,8 +76,6 @@ const defaultCssModuleOption: PostcssOption.cssModules = { } } -const staticDirectory = 'static' - const getLoader = (loaderName: string, options: IOption) => { return { loader: require.resolve(loaderName), @@ -115,7 +113,6 @@ export const getLessLoader = pipe(mergeOption, partial(getLoader, 'less-loader') export const getStylusLoader = pipe(mergeOption, partial(getLoader, 'stylus-loader')) export const getUrlLoader = pipe(mergeOption, partial(getLoader, 'url-loader')) export const getFileLoader = pipe(mergeOption, partial(getLoader, 'file-loader')) -export const getFileParseLoader = pipe(mergeOption, partial(getLoader, path.resolve(__dirname, '../loaders/fileParseLoader'))) export const getWxTransformerLoader = pipe(mergeOption, partial(getLoader, path.resolve(__dirname, '../loaders/wxTransformerLoader'))) export const getMiniTemplateLoader = pipe(mergeOption, partial(getLoader, path.resolve(__dirname, '../loaders/miniTemplateLoader'))) @@ -273,7 +270,7 @@ export const getModule = (appPath: string, { const stylusLoader = getStylusLoader([{ sourceMap: enableSourceMap }, stylusLoaderOption]) - const fileParseLoader = getFileParseLoader([{ + const wxTransformerLoader = getWxTransformerLoader([{ babel, alias, designWidth, @@ -283,17 +280,13 @@ export const getModule = (appPath: string, { sourceDir }]) - const wxTransformerLoader = getWxTransformerLoader([{ - buildAdapter - }]) - const miniTemplateLoader = getMiniTemplateLoader([{ buildAdapter }]) let scriptsLoaderConf = { test: REG_SCRIPTS, - use: [fileParseLoader, wxTransformerLoader], + use: [wxTransformerLoader], } if (compileExclude && compileExclude.length) {