diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d6a2cbb6..935e3d42 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -39,7 +39,7 @@ jobs: - run: npm run build:express - run: npm run build:hapi - run: npm run build:react-component - - run: npm run build:react-component:doc + - run: npm run build:react-component-tsx # - name: Build and Deploy # uses: peaceiris/actions-gh-pages@v2.5.0 diff --git a/example/react-component-tsx/.kktrc.ts b/example/react-component-tsx/.kktrc.ts index fb414edf..d0d7c621 100644 --- a/example/react-component-tsx/.kktrc.ts +++ b/example/react-component-tsx/.kktrc.ts @@ -1,19 +1,25 @@ import path from 'path'; -import { OptionConf } from 'kkt'; -import webpack from 'webpack'; +import webpack, { Configuration } from 'webpack'; +import { DevServerConfigFunction, LoaderConfOptions } from 'kkt'; +import WebpackDevServer from 'webpack-dev-server'; +import lessModules from '@kkt/less-modules'; +import rawModules from '@kkt/raw-modules'; +import scopePluginOptions from '@kkt/scope-plugin-options'; +import pkg from './package.json'; -type Webpack = typeof webpack; - -export const loaderOneOf = [require.resolve('@kkt/loader-less')]; - -export default (conf: webpack.Configuration, opts: OptionConf, webpack: Webpack) => { - const pkg = require(path.resolve(process.cwd(), 'package.json')); - // 获取版本 +export default (conf: Configuration, env: string, options: LoaderConfOptions) => { + conf = rawModules(conf, env, { ...options }); + conf = scopePluginOptions(conf, env, { + ...options, + allowedFiles: [path.resolve(process.cwd(), 'README.md')], + }); + conf = lessModules(conf, env, options); + // Get the project version. conf.plugins!.push( new webpack.DefinePlugin({ VERSION: JSON.stringify(pkg.version), }), ); - + conf.output = { ...conf.output, publicPath: './' }; return conf; }; diff --git a/example/react-component-tsx/.prettierignore b/example/react-component-tsx/.prettierignore new file mode 100644 index 00000000..d9b95702 --- /dev/null +++ b/example/react-component-tsx/.prettierignore @@ -0,0 +1,10 @@ +**/*.md +**/*.svg +**/*.ejs +**/*.yml +package.json +node_modules +dist +build +lib +test diff --git a/example/react-component-tsx/.prettierrc b/example/react-component-tsx/.prettierrc new file mode 100644 index 00000000..764fbde2 --- /dev/null +++ b/example/react-component-tsx/.prettierrc @@ -0,0 +1,11 @@ +{ + "singleQuote": true, + "trailingComma": "all", + "printWidth": 120, + "overrides": [ + { + "files": ".prettierrc", + "options": { "parser": "json" } + } + ] +} diff --git a/example/react-component-tsx/README.md b/example/react-component-tsx/README.md index f2af866f..9d449f56 100644 --- a/example/react-component-tsx/README.md +++ b/example/react-component-tsx/README.md @@ -1,21 +1,37 @@ -react-component-tsx +React Component Example for TypeScript. === -为 React 组件库创建一个项目,包含组件库实例预览的网站。文档与组件库放入一个工程中,全部使用 TypeScript 编写,React 组件库源文件放入 `src` 目录 ,文档网站源文件放入 `website` 目录。 +Create a project for the React component library containing a website preview of the component library instance. The documents and component libraries are put into a project, all written in `TypeScript`, the component library source files are added to the `src` directory, and the document website source files are added to the `website` directory. -## 开发模式 +## Open in CodeSandbox + +[![Open in CodeSandbox](https://img.shields.io/badge/Open%20in-CodeSandbox-blue?logo=codesandbox)](https://codesandbox.io/s/github/jaywcjlove/example/react-component-tsx) + +## Quick Start + +```bash +npm install +``` + +**development** + +Runs the project in development mode. ```bash -# 第一步,先运行,监听组件编译输出 .js 文件 -npm run ts:watch -# 第二步,监听编译输出类型 .d.ts 文件 -npm run types:watch -# 第三步,开发模式,监听编译预览网站实例 -npm run doc:dev +# Step 1, run first, listen to the component compile and output the .js file +# listen for compilation output type .d.ts file +npm run watch +# Step 2, development mode, listen to compile preview website instance +npm run start ``` -编译发布 +**production** + +Builds the app for production to the build folder. ```bash -npm run released -``` \ No newline at end of file +npm run build +``` + +The build is minified and the filenames include the hashes. +Your app is ready to be deployed! \ No newline at end of file diff --git a/example/react-component-tsx/package.json b/example/react-component-tsx/package.json index c0a5365f..d524e9fe 100644 --- a/example/react-component-tsx/package.json +++ b/example/react-component-tsx/package.json @@ -1,22 +1,25 @@ { "name": "@template/react-component-tsx", - "version": "2.0.0", + "version": "6.2.0", + "description": "React Component Example for TypeScript.", "private": true, - "description": "", "main": "lib/cjs/index.js", "module": "lib/esm/index.js", "scripts": { - "doc": "ENTRYDIR=website kkt build", - "doc:dev": "ENTRYDIR=website kkt start", - "build": "npm run ts:build && npm run types:esm && npm run types:cjs && npm run css:build", - "watch": "npm run types:watch & npm run ts:watch", + "doc": "kkt build --app-src ./website", + "start": "kkt start --app-src ./website", + "build": "npm run build:lib && npm run doc", + "build:lib": "npm run ts:build && npm run types:esm && npm run types:cjs && npm run css:build", + "watch": "npm run ts:watch & npm run types:watch & npm run css:watch", "types:build": "tsbb types --sourceRoot src --target ESNEXT", "types:watch": "npm run types:esm -- --watch & npm run types:cjs -- --watch", "types:esm": "npm run types:build -- --outDir ../lib/esm", "types:cjs": "npm run types:build -- --outDir ../lib/cjs", "css:build": "compile-less -d src -o lib/esm", + "css:watch": "compile-less -d src -o lib/esm --watch", "ts:watch": "tsbb watch --env-name esm:dev --env-name cjs --target react", - "ts:build": "tsbb build --target react" + "ts:build": "tsbb build --target react", + "prettier": "prettier --write \"**/*.{js,jsx,tsx,ts,less,md,json}\"" }, "repository": { "type": "git", @@ -24,21 +27,45 @@ }, "author": "", "license": "MIT", + "husky": { + "hooks": { + "pre-commit": "lint-staged" + } + }, + "lint-staged": { + "*.{js,jsx,tsx,ts,less,md,json}": [ + "prettier --write \"**/*.{js,jsx,tsx,ts,less,md,json}\"" + ] + }, + "peerDependencies": { + "@babel/runtime": ">=7.10.0", + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + }, "dependencies": { - "classnames": "^2.2.6", - "prop-types": "^15.7.2", - "react": "^16.12.0", - "react-dom": "^16.12.0" + "prop-types": "15.7.2" }, "devDependencies": { - "@kkt/loader-less": "5.10.3", - "@types/classnames": "2.2.11", - "@types/react": "16.9.35", - "@types/react-dom": "16.9.8", - "compile-less-cli": "1.5.1", - "kkt": "5.10.3", + "@kkt/less-modules": "6.2.0", + "@kkt/raw-modules": "6.2.0", + "@kkt/scope-plugin-options": "6.2.0", + "@types/react": "17.0.0", + "@types/react-dom": "17.0.0", + "compile-less-cli": "1.6.0", + "husky": "4.3.7", + "kkt": "6.2.0", + "lint-staged": "10.5.3", + "prettier": "2.2.1", + "react": "17.0.1", + "react-dom": "17.0.1", "tsbb": "2.0.0" }, + "eslintConfig": { + "extends": [ + "react-app", + "react-app/jest" + ] + }, "browserslist": { "production": [ ">0.2%", diff --git a/example/react-component-tsx/public/index.html b/example/react-component-tsx/public/index.html index 40e7a6c9..a83fc7fa 100644 --- a/example/react-component-tsx/public/index.html +++ b/example/react-component-tsx/public/index.html @@ -2,14 +2,38 @@ - - - - KKT + + + + + + + React App +
+ - + \ No newline at end of file diff --git a/example/react-component-tsx/sandbox.config.json b/example/react-component-tsx/sandbox.config.json new file mode 100644 index 00000000..a4df8557 --- /dev/null +++ b/example/react-component-tsx/sandbox.config.json @@ -0,0 +1,3 @@ +{ + "template": "node" +} diff --git a/example/react-component-tsx/src/index.tsx b/example/react-component-tsx/src/index.tsx index 2a54fbef..b6e8318e 100644 --- a/example/react-component-tsx/src/index.tsx +++ b/example/react-component-tsx/src/index.tsx @@ -1,6 +1,5 @@ import React from 'react'; import PropTypes from 'prop-types'; -import classnames from 'classnames'; import styles from './style/index.module.less'; import './style/index.less'; @@ -32,16 +31,21 @@ export default function Button(props: ButtonProps = {}) { htmlType, ...others } = props; - const cls = classnames(className, prefixCls, styles.test, { - [`${prefixCls}-${size}`]: size, - [`${prefixCls}-${type}`]: type, - [`${prefixCls}-basic`]: basic, - [`${prefixCls}-loading`]: loading, // 加载 - disabled: disabled || loading, // 禁用状态 - active, // 激活状态 - block, // 块级元素Block level - }); - /* eslint-disable */ + + const cls = [ + className, + prefixCls, + styles.test, + size ? `${prefixCls}-${size}` : false, + type ? `${prefixCls}-${type}` : false, + basic ? `${prefixCls}-basic` : false, + loading ? `${prefixCls}-loading` : false, + disabled || loading ? 'disabled' : false, + active ? 'active' : false, + block ? 'block' : false, + ] + .filter(Boolean) + .join(' '); return ( +
{MDStr}
); diff --git a/example/react-component-tsx/website/react-app-env.d.ts b/example/react-component-tsx/website/react-app-env.d.ts index 73039c35..09ddb708 100644 --- a/example/react-component-tsx/website/react-app-env.d.ts +++ b/example/react-component-tsx/website/react-app-env.d.ts @@ -1,78 +1,6 @@ -/// -/// -/// - -declare namespace NodeJS { - interface ProcessEnv { - readonly NODE_ENV: 'development' | 'production' | 'test'; - readonly PUBLIC_URL: string; - } -} - -declare module '*.bmp' { - const src: string; - export default src; -} - -declare module '*.gif' { - const src: string; - export default src; -} - -declare module '*.jpg' { - const src: string; - export default src; -} - -declare module '*.jpeg' { - const src: string; - export default src; -} - -declare module '*.png' { - const src: string; - export default src; -} - -declare module '*.webp' { - const src: string; - export default src; -} - -declare module '*.svg' { - import * as React from 'react'; - - export const ReactComponent: React.FunctionComponent>; - - const src: string; - export default src; -} +/// declare module '*.module.less' { const classes: { readonly [key: string]: string }; export default classes; } - -declare module '*.less' { - const src: string; - export default src; -} -declare module '*.md' { - const src: string; - export default src; -} - -declare module '*.module.css' { - const classes: { readonly [key: string]: string }; - export default classes; -} - -declare module '*.module.scss' { - const classes: { readonly [key: string]: string }; - export default classes; -} - -declare module '*.module.sass' { - const classes: { readonly [key: string]: string }; - export default classes; -} diff --git a/example/react-component-tsx/website/serviceWorker.ts b/example/react-component-tsx/website/serviceWorker.ts deleted file mode 100644 index 988150bd..00000000 --- a/example/react-component-tsx/website/serviceWorker.ts +++ /dev/null @@ -1,133 +0,0 @@ -// This optional code is used to register a service worker. -// register() is not called by default. - -// This lets the app load faster on subsequent visits in production, and gives -// it offline capabilities. However, it also means that developers (and users) -// will only see deployed updates on subsequent visits to a page, after all the -// existing tabs open on the page have been closed, since previously cached -// resources are updated in the background. - -// To learn more about the benefits of this model and instructions on how to -// opt-in, read https://bit.ly/CRA-PWA - -const isLocalhost = Boolean( - window.location.hostname === 'localhost' || - // [::1] is the IPv6 localhost address. - window.location.hostname === '[::1]' || - // 127.0.0.1/8 is considered localhost for IPv4. - window.location.hostname.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/), -); - -type Config = { - onSuccess?: (registration: ServiceWorkerRegistration) => void; - onUpdate?: (registration: ServiceWorkerRegistration) => void; -}; - -export function register(config?: Config) { - if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { - // The URL constructor is available in all browsers that support SW. - const publicUrl = new URL((process as { env: { [key: string]: string } }).env.PUBLIC_URL, window.location.href); - if (publicUrl.origin !== window.location.origin) { - // Our service worker won't work if PUBLIC_URL is on a different origin - // from what our page is served on. This might happen if a CDN is used to - // serve assets; see https://github.com/facebook/create-react-app/issues/2374 - return; - } - - window.addEventListener('load', () => { - const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; - - if (isLocalhost) { - // This is running on localhost. Let's check if a service worker still exists or not. - checkValidServiceWorker(swUrl, config); - - // Add some additional logging to localhost, pointing developers to the - // service worker/PWA documentation. - navigator.serviceWorker.ready.then(() => { - console.log( - 'This web app is being served cache-first by a service ' + - 'worker. To learn more, visit https://bit.ly/CRA-PWA', - ); - }); - } else { - // Is not localhost. Just register service worker - registerValidSW(swUrl, config); - } - }); - } -} - -function registerValidSW(swUrl: string, config?: Config) { - navigator.serviceWorker - .register(swUrl) - .then((registration) => { - registration.onupdatefound = () => { - const installingWorker = registration.installing; - if (installingWorker == null) { - return; - } - installingWorker.onstatechange = () => { - if (installingWorker.state === 'installed') { - if (navigator.serviceWorker.controller) { - // At this point, the updated precached content has been fetched, - // but the previous service worker will still serve the older - // content until all client tabs are closed. - console.log( - 'New content is available and will be used when all ' + - 'tabs for this page are closed. See https://bit.ly/CRA-PWA.', - ); - - // Execute callback - if (config && config.onUpdate) { - config.onUpdate(registration); - } - } else { - // At this point, everything has been precached. - // It's the perfect time to display a - // "Content is cached for offline use." message. - console.log('Content is cached for offline use.'); - - // Execute callback - if (config && config.onSuccess) { - config.onSuccess(registration); - } - } - } - }; - }; - }) - .catch((error) => { - console.error('Error during service worker registration:', error); - }); -} - -function checkValidServiceWorker(swUrl: string, config?: Config) { - // Check if the service worker can be found. If it can't reload the page. - fetch(swUrl) - .then((response) => { - // Ensure service worker exists, and that we really are getting a JS file. - const contentType = response.headers.get('content-type'); - if (response.status === 404 || (contentType != null && contentType.indexOf('javascript') === -1)) { - // No service worker found. Probably a different app. Reload the page. - navigator.serviceWorker.ready.then((registration) => { - registration.unregister().then(() => { - window.location.reload(); - }); - }); - } else { - // Service worker found. Proceed as normal. - registerValidSW(swUrl, config); - } - }) - .catch(() => { - console.log('No internet connection found. App is running in offline mode.'); - }); -} - -export function unregister() { - if ('serviceWorker' in navigator) { - navigator.serviceWorker.ready.then((registration) => { - registration.unregister(); - }); - } -} diff --git a/package.json b/package.json index 5d7d3749..7cee6884 100644 --- a/package.json +++ b/package.json @@ -6,8 +6,8 @@ "build:basic": "lerna exec \"npm run build\" --scope @template/basic --stream", "build:express": "lerna exec \"npm run build\" --scope @template/express --stream", "build:hapi": "lerna exec \"npm run build\" --scope @template/hapi --stream", - "build:react-component": "lerna exec \"npm run build\" --scope @template/react-component --stream", - "build:react-component:doc": "lerna exec \"npm run doc\" --scope @template/react-component --stream", + "build:react-component": "lerna exec \"npm run build && npm run doc\" --scope @template/react-component --stream", + "build:react-component-tsx": "lerna exec \"npm run build\" --scope @template/react-component --stream", "watch": "lerna exec \"tsc -p ./ --types --outDir lib --watch\" --scope tsbb --scope @tsbb/* --stream", "build": "lerna exec \"tsc -p ./ --types --outDir lib\" --scope tsbb --scope @tsbb/* --stream", "type-check": "lerna exec \"tsc --noEmit\" --scope tsbb --scope @tsbb/* --stream",