Skip to content

Commit

Permalink
fix(cli): 修复 watch 时文件修改不对的问题
Browse files Browse the repository at this point in the history
  • Loading branch information
luckyadam committed Jan 7, 2020
1 parent 39ef6a9 commit 1620d9d
Show file tree
Hide file tree
Showing 3 changed files with 220 additions and 10 deletions.
12 changes: 2 additions & 10 deletions packages/taro-mini-runner/src/plugins/MiniPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import * as FunctionModulePlugin from 'webpack/lib/FunctionModulePlugin'
import * as JsonpTemplatePlugin from 'webpack/lib/web/JsonpTemplatePlugin'
import * as NodeSourcePlugin from 'webpack/lib/node/NodeSourcePlugin'
import * as LoaderTargetPlugin from 'webpack/lib/LoaderTargetPlugin'
import * as VirtualModulePlugin from 'virtual-module-webpack-plugin'
import { merge, defaults, kebabCase } from 'lodash'
import * as t from 'babel-types'
import traverse from 'babel-traverse'
Expand All @@ -22,6 +21,7 @@ import TaroSingleEntryDependency from '../dependencies/TaroSingleEntryDependency

import TaroLoadChunksPlugin from './TaroLoadChunksPlugin'
import TaroNormalModulesPlugin from './TaroNormalModulesPlugin'
import VirtualModulePlugin from './VirtualModulePlugin/VirtualModulePlugin'

interface IMiniPluginOptions {
appEntry?: string,
Expand Down Expand Up @@ -153,15 +153,7 @@ export default class MiniPlugin {
compiler.hooks.watchRun.tapAsync(
PLUGIN_NAME,
this.tryAsync(async (compiler: webpack.Compiler) => {
const changedTimes = compiler.watchFileSystem.watcher.mtimes
const changedFiles = Object.keys(changedTimes)
.map(file => `\n ${file}`)
.join('')
if (changedFiles.length) {
console.log(changedFiles)
} else {
await this.run(compiler)
}
this.run(compiler)
})
)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import * as path from 'path'
import VirtualStats from './virtualStats'

export default class VirtualModulePlugin {
options: {
moduleName: string
contents: any
path?: string
}
constructor (options) {
this.options = options
}

apply(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) { // [email protected] or greater
fs._statStorage.data.set(modulePath, [null, stats])
} else { // [email protected] or lower
fs._statStorage.data[modulePath] = [null, stats]
}
if (readFileStorageIsMap) { // [email protected] or greater
fs._readFileStorage.data.set(modulePath, [null, contents])
} else { // [email protected] 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,
})
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/**
* 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)
}
}

0 comments on commit 1620d9d

Please sign in to comment.