Skip to content

Commit 2b18457

Browse files
committed
Add global styles & update webpack config
1 parent 5f3d2fa commit 2b18457

File tree

9 files changed

+911
-27
lines changed

9 files changed

+911
-27
lines changed

package.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,18 +39,23 @@
3939
"@babel/preset-react": "^7.16.7",
4040
"@babel/register": "^7.17.7",
4141
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.5",
42+
"@teamsupercell/typings-for-css-modules-loader": "^2.5.1",
4243
"@types/jest": "^27.4.1",
4344
"@types/node": "^16.11.26",
4445
"@types/react": "^18.0.5",
4546
"@types/react-dom": "^18.0.1",
4647
"@typescript-eslint/eslint-plugin": "^5.19.0",
4748
"@typescript-eslint/parser": "^5.19.0",
49+
"autoprefixer": "^10.4.7",
4850
"babel-eslint": "^10.1.0",
4951
"babel-loader": "^8.2.4",
5052
"clean-webpack-plugin": "^4.0.0",
5153
"copy-webpack-plugin": "^10.2.4",
5254
"core-js": "^3.22.0",
5355
"cross-env": "^7.0.3",
56+
"css-loader": "^6.7.1",
57+
"cssnano": "^5.1.10",
58+
"dotenv-webpack": "^7.1.0",
5459
"eslint": "^8.13.0",
5560
"eslint-config-airbnb-base": "^15.0.0",
5661
"eslint-config-airbnb-typescript": "^17.0.0",
@@ -64,11 +69,20 @@
6469
"fork-ts-checker-webpack-plugin": "^7.2.6",
6570
"html-loader": "^3.1.0",
6671
"html-webpack-plugin": "^5.5.0",
72+
"less": "^4.1.2",
73+
"less-loader": "^11.0.0",
74+
"mini-css-extract-plugin": "^2.6.0",
6775
"path": "^0.12.7",
76+
"postcss": "^8.4.14",
77+
"postcss-loader": "^7.0.0",
6878
"prettier": "^2.6.2",
6979
"pretty-quick": "^3.1.3",
7080
"react-refresh": "^0.12.0",
7181
"resolve-url-loader": "^5.0.0",
82+
"sass": "^1.52.1",
83+
"sass-loader": "^13.0.0",
84+
"sass-resources-loader": "^2.2.5",
85+
"style-loader": "^3.3.1",
7286
"terser-webpack-plugin": "^5.3.1",
7387
"ts-loader": "^9.2.8",
7488
"typescript": "^4.6.3",

src/index.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ import { createRoot } from 'react-dom/client';
44
// Components.
55
import App from '@/app';
66

7+
// Global styles.
8+
import '@/styles/styles.scss';
9+
710
const rootElement = document.getElementById('root');
811
const root = createRoot(rootElement as Element);
912

src/styles/_global.scss

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
:root {
2+
--color-background: #f5f5f9;
3+
--color-scrollbar: rgb(224, 224, 224);
4+
--color-scrollbar-hover: #bbb;
5+
}
6+
::-webkit-scrollbar {
7+
width: 6px;
8+
height: 6px;
9+
}
10+
::-webkit-scrollbar-track,
11+
::-webkit-scrollbar-corner {
12+
background: var(--color-background);
13+
border-radius: 10px;
14+
}
15+
::-webkit-scrollbar-thumb {
16+
background: var(--color-scrollbar);
17+
border-radius: 10px;
18+
}
19+
::-webkit-scrollbar-track,
20+
::-webkit-scrollbar-corner {
21+
background: var(--color-background);
22+
border-radius: 10px;
23+
}

src/styles/styles.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@import 'global';

webpack-config/plugins.js

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
import { join } from 'path';
2-
import { DefinePlugin, ProvidePlugin } from 'webpack';
2+
3+
import { CleanWebpackPlugin } from 'clean-webpack-plugin';
34
import CopyWebpackPlugin from 'copy-webpack-plugin';
4-
import HtmlWebpackPlugin from 'html-webpack-plugin';
5+
import Dotenv from 'dotenv-webpack';
56
import ESLintWebpackPlugin from 'eslint-webpack-plugin';
6-
import { CleanWebpackPlugin } from 'clean-webpack-plugin';
77
import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin';
8-
import { rootDir, isDev, isDevServer, isProd, mode } from './utils';
8+
import HtmlWebpackPlugin from 'html-webpack-plugin';
9+
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
10+
import { DefinePlugin, ProvidePlugin } from 'webpack';
11+
12+
import { isDev, isDevServer, isProd, mode, rootDir } from './utils';
913

1014
/**
1115
* Automatic load modules instead of having to import them anywhere.
@@ -18,9 +22,7 @@ export const providePlugin = new ProvidePlugin({});
1822
* @see https://webpack.js.org/plugins/define-plugin/
1923
*/
2024
export const definePlugin = new DefinePlugin({
21-
'process.env': {
22-
NODE_ENV: JSON.stringify(mode),
23-
},
25+
'process.env.NODE_ENV': JSON.stringify(mode),
2426
IS_PROD: isProd,
2527
IS_DEV: isDev,
2628
IS_DEV_SERVER: isDevServer,
@@ -69,5 +71,23 @@ export const forkTsCheckerWebpackPlugin = new ForkTsCheckerWebpackPlugin({
6971
async: isDev,
7072
typescript: {
7173
configFile: join(rootDir, '/tsconfig.json'),
74+
memoryLimit: 4096,
7275
},
7376
});
77+
78+
/**
79+
* Mini css plugin
80+
* @see https://webpack.js.org/plugins/mini-css-extract-plugin/
81+
*/
82+
export const miniCssExtractPlugin = new MiniCssExtractPlugin({
83+
// Options similar to the same options in webpackOptions.output
84+
// both options are optional
85+
filename: '[name].[contenthash].css',
86+
chunkFilename: '[id].[contenthash].css',
87+
});
88+
89+
/**
90+
* Dot env plugin webpack
91+
* @see https://github.com/mrsteele/dotenv-webpack
92+
*/
93+
export const dotEnvPlugin = new Dotenv({});

webpack-config/rules.js

Lines changed: 201 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,18 @@
11
import { join } from 'path';
2-
import { rootDir } from './utils';
2+
3+
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
4+
5+
import { isProd, rootDir } from './utils';
6+
7+
/**
8+
* Resource list for sass-resource-loader
9+
* @see https://github.com/shakacode/sass-resources-loader
10+
* @example
11+
* [
12+
* path.resolve(__dirname, '../src/foo.scss'),
13+
* ]
14+
*/
15+
const sassResourceItems = [];
316

417
/**
518
* @see https://webpack.js.org/guides/typescript/#loader
@@ -55,3 +68,190 @@ export const fontsRule = {
5568
test: /\.(woff(2)?|eot|ttf|otf|)$/i,
5669
type: 'asset/inline',
5770
};
71+
72+
/***
73+
* Using MiniCssExtractPlugin in production or style-loader in development
74+
* @see https://webpack.js.org/plugins/mini-css-extract-plugin/#root
75+
* @see https://webpack.js.org/loaders/style-loader/#root
76+
*/
77+
const miniCssExtractLoader = isProd
78+
? {
79+
loader: MiniCssExtractPlugin.loader,
80+
options: {
81+
esModule: false,
82+
},
83+
}
84+
: {
85+
loader: 'style-loader',
86+
options: {
87+
esModule: false,
88+
},
89+
};
90+
91+
const postCssLoader = {
92+
loader: 'postcss-loader',
93+
options: {
94+
postcssOptions: {
95+
plugins: ['autoprefixer', isProd ? 'cssnano' : null],
96+
},
97+
sourceMap: true,
98+
},
99+
};
100+
101+
/**
102+
* @see https://webpack.js.org/loaders/sass-loader/#problems-with-url
103+
*/
104+
const resolveUrlLoader = {
105+
loader: 'resolve-url-loader',
106+
options: {
107+
sourceMap: true,
108+
},
109+
};
110+
111+
const typingsCssModulesLoader = {
112+
loader: '@teamsupercell/typings-for-css-modules-loader',
113+
options: {
114+
banner: '// autogenerated by typings-for-css-modules-loader. \n// Please do not change this file!',
115+
formatter: 'prettier',
116+
},
117+
};
118+
119+
const cssModulesSupportLoaderItems = [
120+
miniCssExtractLoader,
121+
typingsCssModulesLoader,
122+
{
123+
loader: 'css-loader',
124+
options: {
125+
esModule: false,
126+
modules: {
127+
exportLocalsConvention: 'camelCaseOnly',
128+
localIdentName: '[local]__[contenthash:base64:5]',
129+
},
130+
},
131+
},
132+
];
133+
134+
/**
135+
* @see https://webpack.js.org/loaders/less-loader/#root
136+
*/
137+
export const lessLoader = {
138+
loader: 'less-loader',
139+
options: {
140+
sourceMap: true,
141+
lessOptions: {
142+
javascriptEnabled: true,
143+
},
144+
},
145+
};
146+
147+
const cssLoaderItems = [
148+
miniCssExtractLoader,
149+
{
150+
loader: 'css-loader',
151+
},
152+
];
153+
154+
/**
155+
* CSS Rule
156+
*/
157+
export const cssRule = {
158+
test: /\.css$/,
159+
use: [
160+
miniCssExtractLoader,
161+
{
162+
loader: 'css-loader',
163+
},
164+
postCssLoader,
165+
],
166+
};
167+
168+
/**
169+
* LESS Rule
170+
*/
171+
export const lessRules = [
172+
{
173+
test: /\.module.less$/,
174+
use: [...cssModulesSupportLoaderItems, postCssLoader, resolveUrlLoader, lessLoader],
175+
},
176+
{
177+
test: /\.less$/,
178+
exclude: /\.module.less$/,
179+
use: [...cssLoaderItems, postCssLoader, resolveUrlLoader, lessLoader],
180+
},
181+
];
182+
183+
/**
184+
* SASS Rule
185+
*/
186+
export const sassRules = [
187+
{
188+
test: /\.module\.s([ca])ss$/,
189+
use: [
190+
...cssModulesSupportLoaderItems,
191+
postCssLoader,
192+
resolveUrlLoader,
193+
{
194+
loader: 'sass-loader',
195+
options: {
196+
sourceMap: true,
197+
implementation: require('sass'), // Prefer `dart-sassRules`
198+
},
199+
},
200+
],
201+
},
202+
{
203+
test: /\.s([ca])ss$/,
204+
exclude: /\.module.scss$/,
205+
use: [
206+
...cssLoaderItems,
207+
postCssLoader,
208+
resolveUrlLoader,
209+
{
210+
loader: 'sass-loader',
211+
options: {
212+
sourceMap: true,
213+
implementation: require('sass'), // Prefer `dart-sassRules`
214+
},
215+
},
216+
],
217+
},
218+
];
219+
220+
/**
221+
* SVG Rule
222+
*/
223+
export const svgRule = [
224+
/**
225+
* Using @svgr/webpack for handling svg files in react components
226+
* @see https://react-svgr.com/docs/webpack/
227+
*/
228+
{
229+
test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
230+
issuer: /\.[jt]sx$/,
231+
use: [
232+
{
233+
loader: 'babel-loader',
234+
options: {
235+
configFile: join(rootDir, '/.babelrc.js'),
236+
},
237+
},
238+
{
239+
loader: '@svgr/webpack',
240+
options: {
241+
babel: false,
242+
icon: true,
243+
},
244+
},
245+
],
246+
},
247+
248+
/**
249+
* Using file-loader for handling svg files
250+
* @see https://webpack.js.org/guides/asset-modules/
251+
*/
252+
{
253+
test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
254+
issuer: { not: [/\.[jt]sx$/] },
255+
type: 'asset/inline',
256+
},
257+
];

webpack-config/utils.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ export const mode = process.env.NODE_ENV ?? 'production';
88
export const isDevServer = process.env.WEBPACK_IS_DEV_SERVER === 'true';
99
export const isProd = mode === 'production';
1010
export const isDev = !isProd;
11+
export const PORT = 3000;

0 commit comments

Comments
 (0)