feat: next
This commit is contained in:
parent
671157aee5
commit
551793c036
12
.babelrc
Normal file
12
.babelrc
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"presets": ["next/babel"],
|
||||
"plugins": [
|
||||
[
|
||||
"import",
|
||||
{
|
||||
"libraryName": "antd",
|
||||
"style": true
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
3
.env.prod
Normal file
3
.env.prod
Normal file
@ -0,0 +1,3 @@
|
||||
NODE_ENV=production
|
||||
CLIENT_BASE_API=/api
|
||||
TTT=production
|
3
.env.release
Normal file
3
.env.release
Normal file
@ -0,0 +1,3 @@
|
||||
NODE_ENV=production
|
||||
CLIENT_BASE_API=/api
|
||||
TTT=release
|
4
.eslintrc.js
Normal file
4
.eslintrc.js
Normal file
@ -0,0 +1,4 @@
|
||||
module.exports = {
|
||||
extends: [],
|
||||
rules: {},
|
||||
};
|
34
.gitignore
vendored
Normal file
34
.gitignore
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.js
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# next.js
|
||||
/.next/
|
||||
/out/
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
*.pem
|
||||
|
||||
# debug
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# local env files
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
# vercel
|
||||
.vercel
|
40
.vscode/settings.json
vendored
Normal file
40
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
{
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": true
|
||||
},
|
||||
"eslint.validate": [
|
||||
"javascript",
|
||||
"react",
|
||||
"typescript",
|
||||
"typescriptreact",
|
||||
"vue"
|
||||
],
|
||||
"editor.formatOnSave": true,
|
||||
"[typescriptreact]": {
|
||||
"editor.defaultFormatter": null
|
||||
},
|
||||
"[javascript]": {
|
||||
"editor.defaultFormatter": null
|
||||
},
|
||||
"[typescript]": {
|
||||
"editor.defaultFormatter": null
|
||||
},
|
||||
"[javascriptreact]": {
|
||||
"editor.defaultFormatter": null
|
||||
},
|
||||
"[json]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[less]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[scss]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[css]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[jsonc]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
}
|
||||
}
|
35
README.md
35
README.md
@ -1,34 +1 @@
|
||||
## 目前已有脚手架列表
|
||||
|
||||
| 名称 | 说明 | 技术栈 |
|
||||
| ------- | --------------------------- | --------------------- |
|
||||
| nextJs | 基于 React 的服务端渲染方案 | nextJs + axios + antd |
|
||||
| ReactJs | 基于 React 的业务型脚手架 | umiJs + axios + antd |
|
||||
| TaroJs | 基于 React 的多端适配方案 | TaroJs 全家桶 |
|
||||
| Vue | 基于 Vue 的业务型脚手架 | vueJs 全家桶 |
|
||||
| Gulp | 基于 Gulp 的清凉型脚手架 | -- |
|
||||
|
||||
## 快速上手
|
||||
|
||||
### 1. 安装相关依赖
|
||||
|
||||
```js
|
||||
// 推荐
|
||||
yarn global add @nicecode/cli
|
||||
|
||||
// or
|
||||
// npm install @nicecode/cli -g
|
||||
```
|
||||
|
||||
### 2. 运行命令
|
||||
|
||||
```js
|
||||
// 查看脚手架版本号,是否安装成功
|
||||
nice - V
|
||||
```
|
||||
|
||||
### 3. 创建项目
|
||||
|
||||
```js
|
||||
nice create ${项目名称}
|
||||
```
|
||||
# nextjs-template
|
2
next-env.d.ts
vendored
Normal file
2
next-env.d.ts
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/// <reference types="next" />
|
||||
/// <reference types="next/types/global" />
|
67
next-less.config.js
Normal file
67
next-less.config.js
Normal file
@ -0,0 +1,67 @@
|
||||
const cssLoaderConfig = require('@zeit/next-css/css-loader-config');
|
||||
|
||||
module.exports = (nextConfig = {}) => {
|
||||
return Object.assign({}, nextConfig, {
|
||||
webpack(config, options) {
|
||||
if (!options.defaultLoaders) {
|
||||
throw new Error(
|
||||
'This plugin is not compatible with Next.js versions below 5.0.0 https://err.sh/next-plugins/upgrade',
|
||||
);
|
||||
}
|
||||
|
||||
const { dev, isServer } = options;
|
||||
const {
|
||||
cssModules,
|
||||
cssLoaderOptions,
|
||||
postcssLoaderOptions,
|
||||
lessLoaderOptions = {},
|
||||
} = nextConfig;
|
||||
|
||||
options.defaultLoaders.less = cssLoaderConfig(config, {
|
||||
extensions: ['less'],
|
||||
cssModules,
|
||||
cssLoaderOptions,
|
||||
postcssLoaderOptions,
|
||||
dev,
|
||||
isServer,
|
||||
loaders: [
|
||||
{
|
||||
loader: 'less-loader',
|
||||
options: lessLoaderOptions,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
config.module.rules.push({
|
||||
test: /\.less$/,
|
||||
exclude: /node_modules/,
|
||||
use: options.defaultLoaders.less,
|
||||
});
|
||||
|
||||
// 我们禁用了antd的cssModules
|
||||
config.module.rules.push({
|
||||
test: /\.less$/,
|
||||
include: /node_modules/,
|
||||
use: cssLoaderConfig(config, {
|
||||
extensions: ['less'],
|
||||
cssModules: false,
|
||||
cssLoaderOptions: {},
|
||||
dev,
|
||||
isServer,
|
||||
loaders: [
|
||||
{
|
||||
loader: 'less-loader',
|
||||
options: lessLoaderOptions,
|
||||
},
|
||||
],
|
||||
}),
|
||||
});
|
||||
|
||||
if (typeof nextConfig.webpack === 'function') {
|
||||
return nextConfig.webpack(config, options);
|
||||
}
|
||||
|
||||
return config;
|
||||
},
|
||||
});
|
||||
};
|
61
next.config.js
Normal file
61
next.config.js
Normal file
@ -0,0 +1,61 @@
|
||||
const withCSS = require('@zeit/next-css');
|
||||
const withLessExcludeAntd = require('./next-less.config');
|
||||
const lessToJS = require('less-vars-to-js');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
// Where your antd-custom.less file lives
|
||||
const modifyVars = lessToJS(
|
||||
fs.readFileSync(
|
||||
path.resolve(__dirname, './src/styles/antd-custom.less'),
|
||||
'utf8',
|
||||
),
|
||||
);
|
||||
|
||||
require('dotenv').config();
|
||||
|
||||
module.exports = withLessExcludeAntd(
|
||||
withCSS({
|
||||
cssModules: true,
|
||||
cssLoaderOptions: {
|
||||
importLoaders: 1,
|
||||
localIdentName: '[local]___[hash:base64:5]',
|
||||
},
|
||||
lessLoaderOptions: {
|
||||
javascriptEnabled: true,
|
||||
modifyVars, // make your antd custom effective
|
||||
},
|
||||
webpack: (config, { isServer }) => {
|
||||
if (isServer) {
|
||||
const antStyles = /antd\/.*?\/style.*?/;
|
||||
const origExternals = [...config.externals];
|
||||
config.externals = [
|
||||
(context, request, callback) => {
|
||||
if (request.match(antStyles)) return callback();
|
||||
if (typeof origExternals[0] === 'function') {
|
||||
origExternals[0](context, request, callback);
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
},
|
||||
...(typeof origExternals[0] === 'function' ? [] : origExternals),
|
||||
];
|
||||
|
||||
config.module.rules.unshift({
|
||||
test: antStyles,
|
||||
use: 'null-loader',
|
||||
});
|
||||
}
|
||||
// 别名
|
||||
config.resolve.alias['@'] = path.resolve(__dirname, './src');
|
||||
config.resolve.alias['@static'] = path.resolve(__dirname, './static');
|
||||
return config;
|
||||
},
|
||||
env: {
|
||||
CLIENT_BASE_API: process.env.CLIENT_BASE_API,
|
||||
},
|
||||
// 用上面的方式使用a[b]的取值取不到
|
||||
publicRuntimeConfig: {
|
||||
},
|
||||
}),
|
||||
);
|
58
package.json
Normal file
58
package.json
Normal file
@ -0,0 +1,58 @@
|
||||
{
|
||||
"name": "nextjs-template",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"build": "dotenv -e .env next build",
|
||||
"build:test": "dotenv -e .env.test next build",
|
||||
"build:release": "dotenv -e .env.release next build",
|
||||
"build:pre": "dotenv -e .env.pre next build",
|
||||
"build:production": "dotenv -e .env.prod next build",
|
||||
"start": "next start",
|
||||
"lint": "eslint 'src/**/*.{js,jsx,tsx,ts}'",
|
||||
"lint:fix": "eslint 'src/**/*.{js,jsx,tsx,ts}' --fix",
|
||||
"prettier": "prettier --write 'src/**/*.{less,css,md,json}'"
|
||||
},
|
||||
"dependencies": {
|
||||
"antd": "^100.0.1",
|
||||
"axios": "^0.21.1",
|
||||
"next": "10.0.4",
|
||||
"normalize.css": "^8.0.1",
|
||||
"react": "17.0.1",
|
||||
"react-dom": "17.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^14.14.19",
|
||||
"@types/react": "^17.0.0",
|
||||
"@types/react-dom": "^17.0.0",
|
||||
"@types/styled-components": "^5.1.7",
|
||||
"@zeit/next-css": "^1.0.1",
|
||||
"@zeit/next-less": "^1.0.1",
|
||||
"babel-plugin-import": "^1.13.3",
|
||||
"css-loader": "^5.0.1",
|
||||
"dotenv": "^8.2.0",
|
||||
"dotenv-cli": "^4.0.0",
|
||||
"eslint": "^7.32.0",
|
||||
"less": "3.13.1",
|
||||
"less-vars-to-js": "^1.3.0",
|
||||
"lint-staged": "^11.1.2",
|
||||
"null-loader": "^4.0.1",
|
||||
"prettier": "^2.3.2",
|
||||
"typescript": "^4.4.2",
|
||||
"yorkie": "^2.0.0"
|
||||
},
|
||||
"gitHooks": {
|
||||
"pre-commit": "tsc --noEmit && lint-staged"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{js,jsx,ts,tsx}": [
|
||||
"npm run lint:fix",
|
||||
"git add ."
|
||||
],
|
||||
"*.{less,css,md,json}": [
|
||||
"npm run prettier",
|
||||
"git add ."
|
||||
]
|
||||
}
|
||||
}
|
BIN
public/favicon.ico
Normal file
BIN
public/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 66 KiB |
0
src/assets/data/code.json
Normal file
0
src/assets/data/code.json
Normal file
3
src/components/Demo/index.less
Normal file
3
src/components/Demo/index.less
Normal file
@ -0,0 +1,3 @@
|
||||
.container {
|
||||
width: 500px;
|
||||
}
|
15
src/components/Demo/index.tsx
Normal file
15
src/components/Demo/index.tsx
Normal file
@ -0,0 +1,15 @@
|
||||
import React from 'react';
|
||||
import { Button } from 'antd';
|
||||
import styles from './index.less';
|
||||
|
||||
const Demo: React.FunctionComponent = () => {
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<h1>title</h1>
|
||||
<p>demo</p>
|
||||
<Button>Button</Button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Demo;
|
22
src/components/PageHeader/index.tsx
Normal file
22
src/components/PageHeader/index.tsx
Normal file
@ -0,0 +1,22 @@
|
||||
import React from 'react';
|
||||
import Head from 'next/head';
|
||||
|
||||
interface PageHeaderProps {
|
||||
title?: string;
|
||||
}
|
||||
|
||||
const PageHeader: React.FC<PageHeaderProps> = ({ title = 'Uni-Ubi' }) => {
|
||||
return (
|
||||
<div>
|
||||
<Head>
|
||||
<title>{title}</title>
|
||||
<link
|
||||
rel="icon"
|
||||
href={require('../../../public/favicon.ico')}
|
||||
/>
|
||||
</Head>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default PageHeader;
|
8
src/interfaces/base.ts
Normal file
8
src/interfaces/base.ts
Normal file
@ -0,0 +1,8 @@
|
||||
export interface IPagination {
|
||||
total: number;
|
||||
size: number;
|
||||
index: number;
|
||||
length: number;
|
||||
beginIndex: number;
|
||||
endIndex: number;
|
||||
}
|
14
src/layouts/BasicLayout/index.tsx
Normal file
14
src/layouts/BasicLayout/index.tsx
Normal file
@ -0,0 +1,14 @@
|
||||
import React from 'react';
|
||||
import PageHeader from '@/components/PageHeader';
|
||||
|
||||
const BasicLayout: React.FC = ({ children }) => {
|
||||
return (
|
||||
<div>
|
||||
<PageHeader />
|
||||
|
||||
<main>{children}</main>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default BasicLayout;
|
7
src/pages/_app.tsx
Normal file
7
src/pages/_app.tsx
Normal file
@ -0,0 +1,7 @@
|
||||
import 'normalize.css/normalize.css';
|
||||
|
||||
function MyApp({ Component, pageProps }) {
|
||||
return <Component {...pageProps} />;
|
||||
}
|
||||
|
||||
export default MyApp;
|
6
src/pages/api/hello.ts
Normal file
6
src/pages/api/hello.ts
Normal file
@ -0,0 +1,6 @@
|
||||
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
|
||||
|
||||
export default (_, res) => {
|
||||
res.statusCode = 200;
|
||||
res.json({ name: 'John Doe' });
|
||||
};
|
11
src/pages/index.tsx
Normal file
11
src/pages/index.tsx
Normal file
@ -0,0 +1,11 @@
|
||||
import BasicLayout from '@/layouts/BasicLayout';
|
||||
import Demo from '@/components/Demo';
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<BasicLayout>
|
||||
<h1>标题</h1>
|
||||
<Demo />
|
||||
</BasicLayout>
|
||||
);
|
||||
}
|
16
src/services/index.ts
Normal file
16
src/services/index.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import clientRequest from '@/utils/clientRequest';
|
||||
|
||||
export interface HelloWordParams {
|
||||
pageIndex?: number;
|
||||
pageSize?: number;
|
||||
keyword: string;
|
||||
}
|
||||
|
||||
// 获取应用列表
|
||||
export const helloWordApi = (params: HelloWordParams): Promise<any> =>{
|
||||
return clientRequest({
|
||||
url: '/test/helloWord',
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
0
src/styles/antd-custom.less
Normal file
0
src/styles/antd-custom.less
Normal file
90
src/styles/var.less
Normal file
90
src/styles/var.less
Normal file
@ -0,0 +1,90 @@
|
||||
// 颜色
|
||||
@S1: #25282a;
|
||||
@S2: #1c21b8;
|
||||
@S3: #2228e0;
|
||||
@S4: #4046ff;
|
||||
@S5: #9ca8ff;
|
||||
@S6: #c9d2ff;
|
||||
@M1: #000000;
|
||||
@M2: #4a4a4a;
|
||||
@M3: #7c7c7c;
|
||||
@M4: #959595;
|
||||
@M5: #c7c7c7;
|
||||
@M6: #e0e0e0;
|
||||
@M7: #f2f2f2;
|
||||
@M8: #f9f9f9;
|
||||
@M9: #ffffff;
|
||||
@D1: #fac105;
|
||||
@D2: #ffab24;
|
||||
@D3: #ff6952;
|
||||
@D4: #ff3c73;
|
||||
@D5: #ee62d5;
|
||||
@D6: #8475ff;
|
||||
@D7: #4f73ff;
|
||||
@D8: #148aff;
|
||||
@D9: #0cc0c9;
|
||||
@D10: #0cc991;
|
||||
@D11: #83d615;
|
||||
@D1-1: #fef8e5;
|
||||
@D2-1: #fff6e9;
|
||||
@D3-1: #fff0ed;
|
||||
@D4-1: #ffebf1;
|
||||
@D5-1: #fdeffa;
|
||||
@D6-1: #f2f1ff;
|
||||
@D7-1: #edf1ff;
|
||||
@D8-1: #e7f3ff;
|
||||
@D9-1: #e6f8f9;
|
||||
@D10-1: #e6f9f3;
|
||||
@D11-1: #f2fae7;
|
||||
@F-info: #4766ff;
|
||||
@F-success: #46cf84;
|
||||
@F-warning: #ffa42e;
|
||||
@F-red: #fa4646;
|
||||
|
||||
/* 字体 */
|
||||
@Fs-1: 12px;
|
||||
@Fs-2: 14px;
|
||||
@Fs-3: 16px;
|
||||
@Fs-4: 18px;
|
||||
@Fs-5: 20px;
|
||||
@Fs-6: 22px;
|
||||
@Fs-7: 24px;
|
||||
@Fs-8: 28px;
|
||||
@Fs-9: 32px;
|
||||
|
||||
/* 行高 */
|
||||
@Lh-1: 20px;
|
||||
@Lh-2: 22px;
|
||||
@Lh-3: 24px;
|
||||
@Lh-4: 26px;
|
||||
@Lh-5: 28px;
|
||||
@Lh-6: 30px;
|
||||
@Lh-7: 32px;
|
||||
@Lh-8: 36px;
|
||||
@Lh-9: 42px;
|
||||
|
||||
// 间距
|
||||
@Sp-1: 2px;
|
||||
@Sp-2: 4px;
|
||||
@Sp-3: 8px;
|
||||
@Sp-4: 10px;
|
||||
@Sp-5: 12px;
|
||||
@Sp-6: 16px;
|
||||
@Sp-7: 20px;
|
||||
@Sp-8: 24px;
|
||||
@Sp-9: 30px;
|
||||
@Sp-10: 32px;
|
||||
@Sp-11: 40px;
|
||||
|
||||
// 阴影
|
||||
@Sh-1: 0 0 8px 0 rgba(0, 0, 0, 0.05);
|
||||
@Sh-2: 0 2px 8px 0 rgba(0, 0, 0, 0.1);
|
||||
@Sh-3: 0 0 12px 0 rgba(0, 0, 0, 0.1);
|
||||
@Sh-4: -4px 0 20px 0 rgba(0, 0, 0, 0.1);
|
||||
@Sh-5: 0 2px 20px 0 rgba(0, 0, 0, 0.3);
|
||||
|
||||
// 圆角
|
||||
@Ra-1: 2px;
|
||||
@Ra-2: 3px;
|
||||
@Ra-3: 6px;
|
||||
@Ra-4: 10px;
|
50
src/utils/clientRequest.ts
Normal file
50
src/utils/clientRequest.ts
Normal file
@ -0,0 +1,50 @@
|
||||
import axios from 'axios';
|
||||
import { message } from 'antd';
|
||||
import { IPagination } from '@/interfaces/base';
|
||||
import codeMsg from '@/assets/data/code.json';
|
||||
|
||||
export interface BaseResponse {
|
||||
code: string;
|
||||
msg: string;
|
||||
memo?: string;
|
||||
data: any;
|
||||
page?: IPagination;
|
||||
result: number;
|
||||
success: boolean;
|
||||
}
|
||||
|
||||
const DEFAULT_TIP_MESSAGE = '请求失败,请刷新重试';
|
||||
|
||||
const handleError = (data: BaseResponse) => {
|
||||
const msg = codeMsg[data.code] || data.msg || DEFAULT_TIP_MESSAGE;
|
||||
message.error(msg);
|
||||
};
|
||||
|
||||
// create an axios instance
|
||||
const service = axios.create({
|
||||
baseURL: process.env.CLIENT_BASE_API, // api的base_url
|
||||
method: 'GET',
|
||||
// timeout: 5000, // request timeout
|
||||
});
|
||||
// request interceptor
|
||||
service.interceptors.request.use(
|
||||
(config) => config,
|
||||
(error) => Promise.reject(error),
|
||||
);
|
||||
|
||||
// response interceptor
|
||||
service.interceptors.response.use(
|
||||
(response) => {
|
||||
const res = response.data;
|
||||
if (!res.success) {
|
||||
handleError(res);
|
||||
}
|
||||
return res;
|
||||
},
|
||||
(error) => {
|
||||
handleError(error);
|
||||
return Promise.reject(error);
|
||||
},
|
||||
);
|
||||
|
||||
export default service;
|
21
src/utils/serverRequest.ts
Normal file
21
src/utils/serverRequest.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import axios from 'axios';
|
||||
|
||||
// create an axios instance
|
||||
const service = axios.create({
|
||||
timeout: 5000, // request timeout
|
||||
withCredentials: true,
|
||||
});
|
||||
|
||||
// request interceptor
|
||||
service.interceptors.request.use(
|
||||
(config) => config,
|
||||
(error) => Promise.reject(error),
|
||||
);
|
||||
|
||||
// response interceptor
|
||||
service.interceptors.response.use(
|
||||
(response) => response,
|
||||
(error) => Promise.reject(error),
|
||||
);
|
||||
|
||||
export default service;
|
24
tsconfig.json
Normal file
24
tsconfig.json
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["src/*"],
|
||||
"@static/*": ["static/*"]
|
||||
},
|
||||
"target": "es5",
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": false,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noEmit": true,
|
||||
"esModuleInterop": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"jsx": "preserve"
|
||||
},
|
||||
"exclude": ["node_modules"],
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"]
|
||||
}
|
3
typings.d.ts
vendored
Normal file
3
typings.d.ts
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
declare module '*.png';
|
||||
declare module '*.css';
|
||||
declare module '*.less';
|
Loading…
Reference in New Issue
Block a user