diff options
Diffstat (limited to '@linaria/packages/webpack4-loader')
-rw-r--r-- | @linaria/packages/webpack4-loader/CHANGELOG.md | 54 | ||||
-rw-r--r-- | @linaria/packages/webpack4-loader/README.md | 35 | ||||
-rw-r--r-- | @linaria/packages/webpack4-loader/babel.config.js | 3 | ||||
-rw-r--r-- | @linaria/packages/webpack4-loader/package.json | 61 | ||||
-rw-r--r-- | @linaria/packages/webpack4-loader/src/index.ts | 167 | ||||
-rw-r--r-- | @linaria/packages/webpack4-loader/tsconfig.json | 5 |
6 files changed, 325 insertions, 0 deletions
diff --git a/@linaria/packages/webpack4-loader/CHANGELOG.md b/@linaria/packages/webpack4-loader/CHANGELOG.md new file mode 100644 index 0000000..c8fca74 --- /dev/null +++ b/@linaria/packages/webpack4-loader/CHANGELOG.md @@ -0,0 +1,54 @@ +# Change Log + +All notable changes to this project will be documented in this file. +See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +# [3.0.0-beta.7](https://github.com/callstack/linaria/compare/v3.0.0-beta.6...v3.0.0-beta.7) (2021-06-24) + + +### Bug Fixes + +* webpack resolve options ([#785](https://github.com/callstack/linaria/issues/785)) ([64b2b06](https://github.com/callstack/linaria/commit/64b2b06edd873d7db0f36ef25a4b9d8389808eb2)) + + + + + +# [3.0.0-beta.6](https://github.com/callstack/linaria/compare/v3.0.0-beta.5...v3.0.0-beta.6) (2021-06-06) + + +### Bug Fixes + +* **webpack:** hot reload fails after compile error (fixes [#762](https://github.com/callstack/linaria/issues/762)) ([#775](https://github.com/callstack/linaria/issues/775)) ([67fcd81](https://github.com/callstack/linaria/commit/67fcd8108f283f8ade23c68ad3fece8aee335bf1)) + + + + + +# [3.0.0-beta.5](https://github.com/callstack/linaria/compare/v3.0.0-beta.4...v3.0.0-beta.5) (2021-05-31) + +**Note:** Version bump only for package @linaria/webpack4-loader + + + + + +# [3.0.0-beta.4](https://github.com/callstack/linaria/compare/v3.0.0-beta.3...v3.0.0-beta.4) (2021-05-07) + +**Note:** Version bump only for package @linaria/webpack4-loader + + + + + +# [3.0.0-beta.3](https://github.com/callstack/linaria/compare/v3.0.0-beta.2...v3.0.0-beta.3) (2021-04-20) + +**Note:** Version bump only for package @linaria/webpack4-loader + + + + + +# [3.0.0-beta.2](https://github.com/callstack/linaria/compare/v3.0.0-beta.1...v3.0.0-beta.2) (2021-04-11) + +**Note:** Version bump only for package @linaria/webpack4-loader diff --git a/@linaria/packages/webpack4-loader/README.md b/@linaria/packages/webpack4-loader/README.md new file mode 100644 index 0000000..0d75b37 --- /dev/null +++ b/@linaria/packages/webpack4-loader/README.md @@ -0,0 +1,35 @@ +<p align="center"> + <img alt="Linaria" src="https://raw.githubusercontent.com/callstack/linaria/HEAD/website/assets/linaria-logo@2x.png" width="496"> +</p> + +<p align="center"> +Zero-runtime CSS in JS library. +</p> + +--- + +### 📖 Please refer to the [GitHub](https://github.com/callstack/linaria#readme) for full documentation. + +## Features + +- Write CSS in JS, but with **zero runtime**, CSS is extracted to CSS files during build +- Familiar **CSS syntax** with Sass like nesting +- Use **dynamic prop based styles** with the React bindings, uses CSS variables behind the scenes +- Easily find where the style was defined with **CSS sourcemaps** +- **Lint your CSS** in JS with [stylelint](https://github.com/stylelint/stylelint) +- Use **JavaScript for logic**, no CSS preprocessor needed +- Optionally use any **CSS preprocessor** such as Sass or PostCSS + +**[Why use Linaria](../../docs/BENEFITS.md)** + +## Installation + +```sh +npm install @linaria/core @linaria/react @linaria/babel-preset @linaria/shaker +``` + +or + +```sh +yarn add @linaria/core @linaria/react @linaria/babel-preset @linaria/shaker +``` diff --git a/@linaria/packages/webpack4-loader/babel.config.js b/@linaria/packages/webpack4-loader/babel.config.js new file mode 100644 index 0000000..c9ad680 --- /dev/null +++ b/@linaria/packages/webpack4-loader/babel.config.js @@ -0,0 +1,3 @@ +const config = require('../../babel.config'); + +module.exports = config; diff --git a/@linaria/packages/webpack4-loader/package.json b/@linaria/packages/webpack4-loader/package.json new file mode 100644 index 0000000..c7fdf8a --- /dev/null +++ b/@linaria/packages/webpack4-loader/package.json @@ -0,0 +1,61 @@ +{ + "name": "@linaria/webpack4-loader", + "version": "3.0.0-beta.7", + "publishConfig": { + "access": "public" + }, + "description": "Blazing fast zero-runtime CSS in JS library", + "main": "lib/index.js", + "module": "esm/index.js", + "types": "types", + "files": [ + "types/", + "lib/", + "esm/" + ], + "license": "MIT", + "repository": "git@github.com:callstack/linaria.git", + "bugs": { + "url": "https://github.com/callstack/linaria/issues" + }, + "homepage": "https://github.com/callstack/linaria#readme", + "keywords": [ + "react", + "linaria", + "css", + "css-in-js", + "styled-components", + "babel-plugin", + "babel" + ], + "scripts": { + "build:lib": "cross-env NODE_ENV=legacy babel src --out-dir lib --extensions '.js,.jsx,.ts,.tsx' --source-maps --delete-dir-on-start", + "build:esm": "babel src --out-dir esm --extensions '.js,.jsx,.ts,.tsx' --source-maps --delete-dir-on-start", + "build": "yarn build:lib && yarn build:esm", + "build:declarations": "tsc --emitDeclarationOnly --outDir types", + "prepare": "yarn build && yarn build:declarations", + "typecheck": "tsc --noEmit --composite false", + "watch": "yarn build --watch" + }, + "devDependencies": { + "@types/cosmiconfig": "^5.0.3", + "@types/enhanced-resolve": "^3.0.6", + "@types/loader-utils": "^1.1.3", + "@types/mkdirp": "^0.5.2", + "@types/normalize-path": "^3.0.0", + "source-map": "^0.7.3" + }, + "dependencies": { + "@linaria/babel-preset": "^3.0.0-beta.7", + "@linaria/logger": "^3.0.0-beta.3", + "cosmiconfig": "^5.1.0", + "enhanced-resolve": "^4.1.0", + "find-yarn-workspace-root": "^1.2.1", + "loader-utils": "^1.2.3", + "mkdirp": "^0.5.1", + "normalize-path": "^3.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7" + } +} diff --git a/@linaria/packages/webpack4-loader/src/index.ts b/@linaria/packages/webpack4-loader/src/index.ts new file mode 100644 index 0000000..c55329a --- /dev/null +++ b/@linaria/packages/webpack4-loader/src/index.ts @@ -0,0 +1,167 @@ +/** + * This file contains a Webpack loader for Linaria. + * It uses the transform.ts function to generate class names from source code, + * returns transformed code without template literals and attaches generated source maps + */ + +import fs from 'fs'; +import path from 'path'; +import mkdirp from 'mkdirp'; +import normalize from 'normalize-path'; +import loaderUtils from 'loader-utils'; +import enhancedResolve from 'enhanced-resolve'; +import findYarnWorkspaceRoot from 'find-yarn-workspace-root'; +import type { RawSourceMap } from 'source-map'; +import cosmiconfig from 'cosmiconfig'; +import { EvalCache, Module, transform } from '@linaria/babel-preset'; +import { debug } from '@linaria/logger'; + +const workspaceRoot = findYarnWorkspaceRoot(); +const lernaConfig = cosmiconfig('lerna', { + searchPlaces: ['lerna.json'], +}).searchSync(); +const lernaRoot = + lernaConfig !== null ? path.dirname(lernaConfig.filepath) : null; + +type LoaderContext = Parameters<typeof loaderUtils.getOptions>[0]; + +const castSourceMap = <T extends { version: number } | { version: string }>( + sourceMap: T | null | undefined +) => + sourceMap + ? { + ...sourceMap, + version: sourceMap.version.toString(), + } + : undefined; + +export default function webpack4Loader( + this: LoaderContext, + content: string, + inputSourceMap: RawSourceMap | null +) { + debug('loader', this.resourcePath); + + EvalCache.clearForFile(this.resourcePath); + + const resolveOptionsDefaults = { + conditionNames: ['require'], + extensions: ['.js', '.jsx', '.ts', '.tsx', '.json'], + }; + + const { + sourceMap = undefined, + cacheDirectory = '.linaria-cache', + preprocessor = undefined, + extension = '.linaria.css', + resolveOptions = {}, + ...rest + } = loaderUtils.getOptions(this) || {}; + + const root = workspaceRoot || lernaRoot || process.cwd(); + + const baseOutputFileName = this.resourcePath.replace(/\.[^.]+$/, extension); + + const outputFilename = normalize( + path.join( + path.isAbsolute(cacheDirectory) + ? cacheDirectory + : path.join(process.cwd(), cacheDirectory), + this.resourcePath.includes(root) + ? path.relative(root, baseOutputFileName) + : baseOutputFileName + ) + ); + + const resolveSync = enhancedResolve.create.sync( + // this._compilation is a deprecated API + // However there seems to be no other way to access webpack's resolver + // There is this.resolve, but it's asynchronous + // Another option is to read the webpack.config.js, but it won't work for programmatic usage + // This API is used by many loaders/plugins, so hope we're safe for a while + { + ...resolveOptionsDefaults, + ...((this._compilation?.options.resolve && { + alias: this._compilation.options.resolve.alias, + modules: this._compilation.options.resolve.modules, + }) || + {}), + ...resolveOptions, + } + ); + + let result; + + const originalResolveFilename = Module._resolveFilename; + + try { + // Use webpack's resolution when evaluating modules + Module._resolveFilename = (id, { filename }) => { + const result = resolveSync(path.dirname(filename), id); + this.addDependency(result); + return result; + }; + + result = transform(content, { + filename: path.relative(process.cwd(), this.resourcePath), + inputSourceMap: inputSourceMap ?? undefined, + outputFilename, + pluginOptions: rest, + preprocessor, + }); + } finally { + // Restore original behaviour + Module._resolveFilename = originalResolveFilename; + } + + if (result.cssText) { + let { cssText } = result; + + if (sourceMap) { + cssText += `/*# sourceMappingURL=data:application/json;base64,${Buffer.from( + result.cssSourceMapText || '' + ).toString('base64')}*/`; + } + + if (result.dependencies?.length) { + result.dependencies.forEach((dep) => { + try { + const f = resolveSync(path.dirname(this.resourcePath), dep); + + this.addDependency(f); + } catch (e) { + // eslint-disable-next-line no-console + console.warn(`[linaria] failed to add dependency for: ${dep}`, e); + } + }); + } + + // Read the file first to compare the content + // Write the new content only if it's changed + // This will prevent unnecessary WDS reloads + let currentCssText; + + try { + currentCssText = fs.readFileSync(outputFilename, 'utf-8'); + } catch (e) { + // Ignore error + } + + if (currentCssText !== cssText) { + mkdirp.sync(path.dirname(outputFilename)); + fs.writeFileSync(outputFilename, cssText); + } + + this.callback( + null, + `${result.code}\n\nrequire(${loaderUtils.stringifyRequest( + this, + outputFilename + )});`, + castSourceMap(result.sourceMap) + ); + return; + } + + this.callback(null, result.code, castSourceMap(result.sourceMap)); +} diff --git a/@linaria/packages/webpack4-loader/tsconfig.json b/@linaria/packages/webpack4-loader/tsconfig.json new file mode 100644 index 0000000..0b7f756 --- /dev/null +++ b/@linaria/packages/webpack4-loader/tsconfig.json @@ -0,0 +1,5 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { "paths": {}, "rootDir": "src/" }, + "references": [{ "path": "../babel" }, { "path": "../logger" }] +} |