Skip to content
This repository was archived by the owner on Apr 6, 2021. It is now read-only.

[Draft] Fix webpack 5 persistent cache invalidation #5

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ node_modules
.DS_Store
dist
dist-ssr
*.local
*.local
.test/
82 changes: 82 additions & 0 deletions src/benchmark.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
const prettier = require('prettier')
const diff = require('jest-diff').default
const postcss = require('postcss')
const tailwind = require('./index.js')
const fs = require('fs/promises')
const path = require('path')
const _ = require('lodash')

function run(input, config = {}) {
return postcss([tailwind(config)]).process(input, { from: undefined })
}

/**
*
* @param {number} count
*/
async function createTestFiles(count) {
const ns = Math.random().toString(16).substr(2, 8)
const testDir = path.normalize(path.join(__dirname, `/../.test/${ns}`))

const utilities = (() => {
const prefixes = _.shuffle(["", "sm:", "hover:", "active:"])
const types = _.shuffle(["h-", "mt-", "max-w-", "foobar-"])
const suffixes = _.shuffle([_.range(0, 1000), "full", "screen"])
const utilities = []

for (let prefix in prefixes) for (let type in types) for (let suffix in suffixes) {
utilities.push(`${prefix}${type}${suffix}`)
}

return utilities
})()

async function createCandidateFile(id) {
const content = utilities.slice(
Math.floor(Math.random() * utilities.length / 4),
Math.floor(Math.random() * utilities.length)
).join("\n")

await fs.writeFile(path.resolve(testDir, `bench_${id}`), content, "utf-8")
}

await fs.mkdir(testDir, { recursive: true })
await Promise.all(_.range(0, count).map(n => createCandidateFile(n)))

return testDir
}

async function bench(count, callback) {
const start = performance.now()

for (let i = 0; i < count; i++) {
await callback();
}

const end = performance.now()

return (end-start) / count;
}

test('bechmark', async () => {
const runPerfTest = async (dir) => {
const config = { purge: [`${dir}/*.css`] }
const content = '@tailwind utilities;'

try {
return await bench(100, () => run(content, config))
} finally {
await fs.rm(dir, { recursive: true, force: true })
}
}

const small = await runPerfTest(await createTestFiles(1e1))
const medium = await runPerfTest(await createTestFiles(1e3))
const large = await runPerfTest(await createTestFiles(1e4))

console.log({small, medium, large})

expect(small).toBeLessThan(20)
expect(medium).toBeLessThan(20)
expect(large).toBeLessThan(20)
})
11 changes: 10 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,9 @@ function cleanupContext(context) {
if (context.watcher) {
context.watcher.close()
}
if (context.touchFile) {
context.touchFile.removeCallback()
}
contextMap.delete(context.configHash)
contextSources.delete(context)
}
Expand All @@ -332,6 +335,7 @@ function rebootTemplateWatcher(context) {
(env.TAILWIND_MODE === undefined && env.NODE_ENV === 'development')
) {
context.touchFile = context.touchFile !== null ? context.touchFile : tmp.fileSync()
env.DEBUG && console.log("Touch file path:", context.touchFile)

Promise.resolve(context.watcher ? context.watcher.close() : null).then(() => {
context.watcher = chokidar.watch(context.candidateFiles, {
Expand Down Expand Up @@ -746,6 +750,7 @@ function setupContext(tailwindConfig, configHash, configPath) {
}

let context = {
dependencies: new Set(),
changedFiles: new Set(),
utilityRuleCache: new Set(),
componentRuleCache: new Set(),
Expand Down Expand Up @@ -958,7 +963,7 @@ module.exports = (pluginOptions = {}) => {
// the work of grabbing all of the template files for candidate
// detection.
if (!context.scannedContent) {
let files = fastGlob.sync(context.candidateFiles)
let files = fastGlob.sync(context.candidateFiles, { absolute: true })
for (let file of files) {
context.changedFiles.add(file)
}
Expand All @@ -973,6 +978,8 @@ module.exports = (pluginOptions = {}) => {

env.DEBUG && console.time('Reading changed files')
for (let file of context.changedFiles) {
context.dependencies.add(file)

let content = fs.readFileSync(file, 'utf8')
getClassCandidates(content, contentMatchCache, candidates, seen)
}
Expand Down Expand Up @@ -1042,6 +1049,7 @@ module.exports = (pluginOptions = {}) => {

if (env.DEBUG) {
console.log('Changed files: ', context.changedFiles.size)
console.log('Dependencies:', context.dependencies.size)
console.log('Potential classes: ', candidates.size)
console.log('Active contexts: ', contextMap.size)
console.log('Active sources:', sourceContextMap.size)
Expand All @@ -1051,6 +1059,7 @@ module.exports = (pluginOptions = {}) => {

// Clear the cache for the changed files
context.changedFiles.clear()
context.dependencies.forEach(registerDependency)
},
function (root) {
if (!foundTailwind) {
Expand Down