Skip to content

feat: Support for opt-in caching #268

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ Please note that no options are required. However, depending on your configurati
| `dotenvOptions` | `{}` | Provides options for [`dotenv`](https://github.com/motdotla/dotenv#options). Note that this plugin only accepts a `string` value for `path`. |
| `postcssOptions` | `{}` | See [`postcssOptions`](#postcssOptions) below. |
| `rendererOptions` | `{}` | See [`rendererOptions`](#rendererOptions) below. |
| `caching` | `"never"` | See [`caching`](#caching) below |

```json
{
Expand Down Expand Up @@ -240,6 +241,19 @@ This is experimental, and may not always work as expected. It currently supports

> For convenience, `loadPaths` for Sass are extended, not replaced. The defaults are the path of the current file, and `'node_modules'`.

#### `caching`

Enables or disables caching.

`"always"` will cache everything. This is overly agressive, and will cause stale types when CSS imported by CSS is modified.
The cache key is the filename of the CSS file directly imported by TypeScript. Restarting the TypeScript server will clear the cache.

`"never"` (default) regenerates types for every CSS file, every time any file is changed. This causes significant latency in editor
operations (autocomplete, import suggestions, etc) in large projects, even when editing non-CSS files.

Unfortunately, there's no balanced option or correct invalidation possible, due to typescript and the various CSS tools having
different module loading systems.

### Visual Studio Code

#### Recommended usage
Expand Down
18 changes: 15 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { getDtsSnapshot } from './helpers/getDtsSnapshot';
import { createLogger } from './helpers/logger';
import { getProcessor } from './helpers/getProcessor';
import { filterPlugins } from './helpers/filterPlugins';
import { IScriptSnapshot } from 'typescript/lib/tsserverlibrary';

const getPostCssConfigPlugins = (directory: string) => {
try {
Expand All @@ -35,6 +36,7 @@ const init: tsModule.server.PluginModuleFactory = ({ typescript: ts }) => {
const logger = createLogger(info);
const directory = info.project.getCurrentDirectory();
const compilerOptions = info.project.getCompilerOptions();
const scriptSnapshotCache = new WeakMap<IScriptSnapshot, IScriptSnapshot>();

const languageServiceHost = {} as Partial<tsModule.LanguageServiceHost>;

Expand Down Expand Up @@ -132,8 +134,16 @@ const init: tsModule.server.PluginModuleFactory = ({ typescript: ts }) => {
};

languageServiceHost.getScriptSnapshot = (fileName) => {
if (isCSS(fileName) && fs.existsSync(fileName)) {
return getDtsSnapshot(
const existingSnapshot =
info.languageServiceHost.getScriptSnapshot(fileName);
if (!isCSS(fileName) || !fs.existsSync(fileName)) return existingSnapshot;

const cachedSnapshot =
existingSnapshot && scriptSnapshotCache.get(existingSnapshot);
if (cachedSnapshot && options.caching === 'always') {
return cachedSnapshot;
} else {
const newSnapshot = getDtsSnapshot(
ts,
processor,
fileName,
Expand All @@ -142,8 +152,10 @@ const init: tsModule.server.PluginModuleFactory = ({ typescript: ts }) => {
compilerOptions,
directory,
);
if (existingSnapshot)
scriptSnapshotCache.set(existingSnapshot, newSnapshot);
return newSnapshot;
}
return info.languageServiceHost.getScriptSnapshot(fileName);
};

const createModuleResolver =
Expand Down
3 changes: 3 additions & 0 deletions src/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,11 @@ export interface Options {
/** @deprecated To align with naming in other projects. */
postCssOptions?: PostcssOptions;
rendererOptions?: RendererOptions;
caching?: CachingOptions;
}

export type CachingOptions = 'always' | 'never';

export type ClassnameTransformOptions =
| 'asIs'
| 'camelCase'
Expand Down