feat: add postcss support

This commit is contained in:
EGOIST 2020-11-27 20:56:25 +08:00
parent 130055a945
commit 743421c65a
9 changed files with 203 additions and 1 deletions

View File

@ -149,6 +149,27 @@ esbuild is fast because it doesn't perform any type checking, you already get ty
Additionally, if you want type checking at build time, you can enable `--dts`, which will run a real TypeScript compiler to generate declaration file so you get type checking as well.
### CSS support
esbuild has [experimental CSS support](https://esbuild.github.io/content-types/#css), and tsup allows you to use PostCSS plugins on top of native CSS support.
To use PostCSS, you need to install PostCSS:
```bash
yarn add postcss --dev
```
..and populate a `postcss.config.js` in your project
```js
module.exports = {
plugins: [
require('tailwindcss')(),
require('autoprefixer')()
]
}
```
---
For more details:

View File

@ -24,6 +24,7 @@
"esbuild": "^0.8.16",
"globby": "^11.0.1",
"joycon": "^2.2.5",
"postcss-load-config": "^3.0.0",
"resolve-from": "^5.0.0",
"rollup": "^2.33.3",
"rollup-plugin-dts": "^1.4.10",
@ -41,6 +42,8 @@
"execa": "^4.1.0",
"fs-extra": "^9.0.1",
"jest": "^26.6.3",
"postcss": "^8.1.10",
"postcss-simple-vars": "^6.0.1",
"prettier": "^2.2.0",
"rollup-plugin-hashbang": "^2.2.2",
"strip-json-comments": "^3.1.1",

View File

@ -8,6 +8,7 @@ import { getDeps, loadTsConfig, loadPkg, getBabel } from './utils'
import { FSWatcher } from 'chokidar'
import glob from 'globby'
import { PrettyError } from './errors'
import { postcssPlugin } from './plugins/postcss'
const textDecoder = new TextDecoder('utf-8')
@ -110,6 +111,7 @@ export async function runEsbuild(
jsxFragment: options.jsxFragment,
sourcemap: options.sourcemap,
target: options.target === 'es5' ? 'es2016' : options.target,
plugins: [postcssPlugin],
define: {
...options.define,
...Object.keys(env).reduce((res, key) => {

50
src/plugins/postcss.ts Normal file
View File

@ -0,0 +1,50 @@
import fs from 'fs'
import path from 'path'
import {Plugin} from 'esbuild'
import { getPostcss } from '../utils'
export const postcssPlugin: Plugin = {
name: 'postcss',
setup(build) {
const configCache = new Map()
build.onLoad({filter: /\.css$/}, async args => {
const loadConfig = await import('postcss-load-config')
const contents = await fs.promises.readFile(args.path, 'utf8')
// Load postcss config
const {plugins, options} = configCache.get(args.path) || (await loadConfig({}, path.dirname(args.path)))
configCache.set(args.path, {plugins, options})
// Return if no postcss plugins are supplied
if (!plugins || plugins.length === 0) {
return {
contents,
loader: 'css'
}
}
// Load postcss
const postcss = getPostcss()
if (!postcss) {
return {
errors: [{
text: `postcss is not installed`
}]
}
}
// Tranform CSS
const result = await postcss?.default(plugins).process(contents, {...options, from: args.path})
return {
contents: result.css,
loader: 'css',
}
})
}
}

View File

@ -82,3 +82,8 @@ export function getBabel(): null | typeof import('@babel/core') {
const p = resovleFrom.silent(process.cwd(), '@babel/core')
return p && require(p)
}
export function getPostcss(): null | typeof import('postcss') {
const p = resovleFrom.silent(process.cwd(), 'postcss')
return p && require(p)
}

View File

@ -39,6 +39,15 @@ Array [
]
`;
exports[`import css: output file 1`] = `"\\"use strict\\";"`;
exports[`import css: output file list 1`] = `
Array [
"input.css",
"input.js",
]
`;
exports[`minify: output file 1`] = `
"\\"use strict\\";Object.defineProperty(exports, \\"__esModule\\", {value: true});function o(){return\\"foo\\"}exports.foo = o;
"

View File

@ -154,3 +154,21 @@ runTest(
flags: ['--env.NODE_ENV', 'production'],
}
)
runTest('import css', {
'input.ts': `
import './foo.css'
`,
'postcss.config.js': `
module.exports = {
plugins: [require('postcss-simple-vars')()]
}
`,
'foo.css': `
$color: blue;
.foo {
color: $color;
}
`
})

3
types.d.ts vendored
View File

@ -1 +1,2 @@
declare module 'rollup-plugin-hashbang'
declare module 'rollup-plugin-hashbang'
declare module 'postcss-load-config'

View File

@ -651,6 +651,11 @@
resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e"
integrity sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==
"@types/parse-json@^4.0.0":
version "4.0.0"
resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0"
integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==
"@types/prettier@^2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.0.0.tgz#dc85454b953178cc6043df5208b9e949b54a3bc4"
@ -1172,6 +1177,11 @@ color-name@~1.1.4:
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
colorette@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.1.tgz#4d0b921325c14faf92633086a536db6e89564b1b"
integrity sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw==
combined-stream@^1.0.6, combined-stream@~1.0.6:
version "1.0.8"
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
@ -1211,6 +1221,17 @@ core-util-is@1.0.2:
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
cosmiconfig@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.0.0.tgz#ef9b44d773959cae63ddecd122de23853b60f8d3"
integrity sha512-pondGvTuVYDk++upghXJabWzL6Kxu6f26ljFw64Swq9v6sQPUL3EUlVDV56diOjpCayKihL6hVe8exIACU4XcA==
dependencies:
"@types/parse-json" "^4.0.0"
import-fresh "^3.2.1"
parse-json "^5.0.0"
path-type "^4.0.0"
yaml "^1.10.0"
cross-spawn@^6.0.0:
version "6.0.5"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
@ -1858,6 +1879,28 @@ ignore@^5.1.4:
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57"
integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==
import-cwd@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/import-cwd/-/import-cwd-3.0.0.tgz#20845547718015126ea9b3676b7592fb8bd4cf92"
integrity sha512-4pnzH16plW+hgvRECbDWpQl3cqtvSofHWh44met7ESfZ8UZOWWddm8hEyDTqREJ9RbYHY8gi8DqmaelApoOGMg==
dependencies:
import-from "^3.0.0"
import-fresh@^3.2.1:
version "3.2.2"
resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.2.2.tgz#fc129c160c5d68235507f4331a6baad186bdbc3e"
integrity sha512-cTPNrlvJT6twpYy+YmKUKrTSjWFs3bjYjAhCwm+z4EOCubZxAuO+hHpRN64TqjEaYSHs7tJAE0w1CKMGmsG/lw==
dependencies:
parent-module "^1.0.0"
resolve-from "^4.0.0"
import-from@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/import-from/-/import-from-3.0.0.tgz#055cfec38cd5a27d8057ca51376d7d3bf0891966"
integrity sha512-CiuXOFFSzkU5x/CR0+z7T91Iht4CXgfCxVOFRhh2Zyhg5wOpWvvDLQUsWl+gcN+QscYBjez8hDCt85O7RLDttQ==
dependencies:
resolve-from "^5.0.0"
import-local@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.0.2.tgz#a8cfd0431d1de4a2199703d003e3e62364fa6db6"
@ -2843,6 +2886,11 @@ mz@^2.7.0:
object-assign "^4.0.1"
thenify-all "^1.0.0"
nanoid@^3.1.18:
version "3.1.18"
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.18.tgz#0680db22ab01c372e89209f5d18283d98de3e96d"
integrity sha512-rndlDjbbHbcV3xi+R2fpJ+PbGMdfBxz5v1fATIQFq0DP64FsicQdwnKLy47K4kZHdRpmQXtz24eGsxQqamzYTA==
nanomatch@^1.2.9:
version "1.2.13"
resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119"
@ -3021,6 +3069,13 @@ p-try@^2.0.0:
resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
parent-module@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2"
integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==
dependencies:
callsites "^3.0.0"
parse-json@^5.0.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.1.0.tgz#f96088cdf24a8faa9aea9a009f2d9d942c999646"
@ -3100,6 +3155,29 @@ posix-character-classes@^0.1.0:
resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab"
integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=
postcss-load-config@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-3.0.0.tgz#850bb066edd65b734329eacf83af0c0764226c87"
integrity sha512-lErrN8imuEF1cSiHBV8MiR7HeuzlDpCGNtaMyYHlOBuJHHOGw6S4xOMZp8BbXPr7AGQp14L6PZDlIOpfFJ6f7w==
dependencies:
cosmiconfig "^7.0.0"
import-cwd "^3.0.0"
postcss-simple-vars@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/postcss-simple-vars/-/postcss-simple-vars-6.0.1.tgz#7733415a7b57f5cb9b5a15cdd6b0546c505e7ad6"
integrity sha512-P1M+APrquBXOPKtk/LlWptuPBwTCjMgxZxv1lkpjG9RdOx8ewi8USOclPCt75xG7UT7viDUB3p3qy2ffPBefjQ==
postcss@^8.1.10:
version "8.1.10"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.1.10.tgz#129834f94c720554d2cfdaeb27d5542ac4a026ea"
integrity sha512-iBXEV5VTTYaRRdxiFYzTtuv2lGMQBExqkZKSzkJe+Fl6rvQrA/49UVGKqB+LG54hpW/TtDBMGds8j33GFNW7pg==
dependencies:
colorette "^1.2.1"
nanoid "^3.1.18"
source-map "^0.6.1"
vfile-location "^3.2.0"
prelude-ls@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
@ -3310,6 +3388,11 @@ resolve-cwd@^3.0.0:
dependencies:
resolve-from "^5.0.0"
resolve-from@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
resolve-from@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69"
@ -4012,6 +4095,11 @@ verror@1.10.0:
core-util-is "1.0.2"
extsprintf "^1.2.0"
vfile-location@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/vfile-location/-/vfile-location-3.2.0.tgz#d8e41fbcbd406063669ebf6c33d56ae8721d0f3c"
integrity sha512-aLEIZKv/oxuCDZ8lkJGhuhztf/BW4M+iHdCwglA/eWc+vtuRFJj8EtgceYFX4LRjOhCAAiNHsKGssC6onJ+jbA==
vlq@^0.2.2:
version "0.2.3"
resolved "https://registry.yarnpkg.com/vlq/-/vlq-0.2.3.tgz#8f3e4328cf63b1540c0d67e1b2778386f8975b26"
@ -4137,6 +4225,11 @@ y18n@^4.0.0:
resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b"
integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==
yaml@^1.10.0:
version "1.10.0"
resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.0.tgz#3b593add944876077d4d683fee01081bd9fff31e"
integrity sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg==
yargs-parser@20.x:
version "20.2.0"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.0.tgz#944791ca2be2e08ddadd3d87e9de4c6484338605"