mirror of
https://github.com/aleleba/create-react-component-library.git
synced 2026-06-20 07:21:09 -06:00
PR-227028: update dependencies, migrate to TypeScript 6 and ESLint flat config
- Bump all dependencies to latest (React 19.2.7, Storybook 10.4.3, Webpack 5.107.2 + webpack-cli 7, Jest 30.4.2, Cypress 15.17.0, Babel 7.29.7, sass-loader 17, css-minimizer-webpack-plugin 8, eslint-webpack-plugin 6). - Migrate TypeScript 5.9 -> 6.0.3: set tsconfig rootDir, add ignoreDeprecations "6.0", scope include to src/components + src/@types, and declare *.scss/*.sass/*.css modules for stricter side-effect imports. - Switch @babel/preset-react to the automatic JSX runtime and drop redundant React imports in stories and tests. - Migrate ESLint from the deprecated .eslintrc.js to flat config (eslint.config.mjs) using typescript-eslint, @eslint/js, globals and the React/Storybook plugins. Keep ESLint at v9 because eslint-plugin-react does not support v10 yet. This fixes the previously broken lint (missing @typescript-eslint parser/plugin) and normalizes formatting. - Fix a latent bug in .storybook/main.js (comma instead of semicolon joining two assignments via the comma operator). - npm audit fix: 0 vulnerabilities. - Bump package version to 1.4.0.
This commit is contained in:
2
.babelrc
2
.babelrc
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"presets": [
|
"presets": [
|
||||||
["@babel/preset-env", {"targets": {"node": "current"}}],
|
["@babel/preset-env", {"targets": {"node": "current"}}],
|
||||||
"@babel/preset-react",
|
["@babel/preset-react", {"runtime": "automatic"}],
|
||||||
"@babel/preset-typescript"
|
"@babel/preset-typescript"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
30
.eslintrc.js
30
.eslintrc.js
@@ -1,30 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
'env': {
|
|
||||||
'browser': true,
|
|
||||||
'node': true,
|
|
||||||
'es2021': true
|
|
||||||
},
|
|
||||||
'extends': ['eslint:recommended', 'plugin:react/recommended', 'plugin:@typescript-eslint/recommended', 'plugin:storybook/recommended', 'plugin:storybook/recommended'],
|
|
||||||
'parser': '@typescript-eslint/parser',
|
|
||||||
'parserOptions': {
|
|
||||||
'ecmaFeatures': {
|
|
||||||
'jsx': true
|
|
||||||
},
|
|
||||||
'ecmaVersion': 'latest',
|
|
||||||
'sourceType': 'module'
|
|
||||||
},
|
|
||||||
'plugins': ['react', '@typescript-eslint'],
|
|
||||||
'rules': {
|
|
||||||
'indent': ['error', 'tab'],
|
|
||||||
'linebreak-style': ['error', 'unix'],
|
|
||||||
'quotes': ['error', 'single'],
|
|
||||||
'semi': ['error', 'always'],
|
|
||||||
'eol-last': ['error', 'always'],
|
|
||||||
'@typescript-eslint/no-var-requires': 0
|
|
||||||
},
|
|
||||||
'settings': {
|
|
||||||
'react': {
|
|
||||||
'version': 'detect'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,81 +1,81 @@
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
|
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
|
||||||
const deFaultValues = {
|
const deFaultValues = {
|
||||||
PREFIX_URL: ''
|
PREFIX_URL: ''
|
||||||
}
|
};
|
||||||
const prefixUrl = process.env.PREFIX_URL ? process.env.PREFIX_URL : deFaultValues.PREFIX_URL;
|
const prefixUrl = process.env.PREFIX_URL ? process.env.PREFIX_URL : deFaultValues.PREFIX_URL;
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|ts|tsx)"],
|
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'],
|
||||||
|
|
||||||
addons: ["@storybook/addon-webpack5-compiler-babel", "@storybook/addon-links", {
|
addons: ['@storybook/addon-webpack5-compiler-babel', '@storybook/addon-links', {
|
||||||
name: '@storybook/addon-styling-webpack',
|
name: '@storybook/addon-styling-webpack',
|
||||||
options: {
|
options: {
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
test: /\.(css|sass|scss)$/,
|
test: /\.(css|sass|scss)$/,
|
||||||
use: [
|
use: [
|
||||||
'style-loader',
|
'style-loader',
|
||||||
{
|
{
|
||||||
loader: 'css-loader',
|
loader: 'css-loader',
|
||||||
options: {
|
options: {
|
||||||
modules: {
|
modules: {
|
||||||
namedExport: false,
|
namedExport: false,
|
||||||
exportLocalsConvention: 'as-is',
|
exportLocalsConvention: 'as-is',
|
||||||
auto: /\.module\.\w+$/i,
|
auto: /\.module\.\w+$/i,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'sass-loader',
|
'sass-loader',
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
}, "@storybook/addon-docs"],
|
}, '@storybook/addon-docs'],
|
||||||
|
|
||||||
webpackFinal: async config => {
|
webpackFinal: async config => {
|
||||||
config.entry = config.entry.map(function(entry) {
|
config.entry = config.entry.map(function(entry) {
|
||||||
if (entry.includes("webpack-hot-middleware")) {
|
if (entry.includes('webpack-hot-middleware')) {
|
||||||
return `${require.resolve('webpack-hot-middleware/client')}?path=${prefixUrl}__webpack_hmr&reload=true`;
|
return `${require.resolve('webpack-hot-middleware/client')}?path=${prefixUrl}__webpack_hmr&reload=true`;
|
||||||
}
|
}
|
||||||
return entry;
|
return entry;
|
||||||
}),
|
});
|
||||||
config.resolve.alias = {
|
config.resolve.alias = {
|
||||||
...config.resolve.alias,
|
...config.resolve.alias,
|
||||||
'@components': path.resolve(__dirname, "../src/components/")
|
'@components': path.resolve(__dirname, '../src/components/')
|
||||||
};
|
};
|
||||||
config.resolve.plugins = [new TsconfigPathsPlugin()];
|
config.resolve.plugins = [new TsconfigPathsPlugin()];
|
||||||
return config;
|
return config;
|
||||||
},
|
},
|
||||||
|
|
||||||
framework: {
|
framework: {
|
||||||
name: "@storybook/react-webpack5",
|
name: '@storybook/react-webpack5',
|
||||||
options: {}
|
options: {}
|
||||||
},
|
},
|
||||||
|
|
||||||
typescript: {
|
typescript: {
|
||||||
reactDocgenTypescriptOptions: {
|
reactDocgenTypescriptOptions: {
|
||||||
compilerOptions: {
|
compilerOptions: {
|
||||||
"paths": {
|
'paths': {
|
||||||
"@Components/*": ["Components/*"]
|
'@Components/*': ['Components/*']
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
propFilter: (prop) => {
|
propFilter: (prop) => {
|
||||||
// Filter out props that might contain Symbol values
|
// Filter out props that might contain Symbol values
|
||||||
if (prop.name && typeof prop.name === 'symbol') {
|
if (prop.name && typeof prop.name === 'symbol') {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Filter out React internal props that might cause issues
|
// Filter out React internal props that might cause issues
|
||||||
if (prop.name && prop.name.startsWith('$$')) {
|
if (prop.name && prop.name.startsWith('$$')) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
docs: {
|
docs: {
|
||||||
autodocs: 'tag',
|
autodocs: 'tag',
|
||||||
defaultName: 'Docs',
|
defaultName: 'Docs',
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,29 +1,29 @@
|
|||||||
export const parameters = {
|
export const parameters = {
|
||||||
actions: { argTypesRegex: "^on[A-Z].*" },
|
actions: { argTypesRegex: '^on[A-Z].*' },
|
||||||
controls: {
|
controls: {
|
||||||
matchers: {
|
matchers: {
|
||||||
color: /(background|color)$/i,
|
color: /(background|color)$/i,
|
||||||
date: /Date$/,
|
date: /Date$/,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
docs: {
|
docs: {
|
||||||
extractArgTypes: (component) => {
|
extractArgTypes: (component) => {
|
||||||
// Filter out Symbol values to prevent serialization errors
|
// Filter out Symbol values to prevent serialization errors
|
||||||
const argTypes = {};
|
const argTypes = {};
|
||||||
if (component && component.propTypes) {
|
if (component && component.propTypes) {
|
||||||
Object.keys(component.propTypes).forEach(key => {
|
Object.keys(component.propTypes).forEach(key => {
|
||||||
const propType = component.propTypes[key];
|
const propType = component.propTypes[key];
|
||||||
// Only include non-Symbol values
|
// Only include non-Symbol values
|
||||||
if (typeof propType !== 'symbol') {
|
if (typeof propType !== 'symbol') {
|
||||||
argTypes[key] = propType;
|
argTypes[key] = propType;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return argTypes;
|
return argTypes;
|
||||||
},
|
},
|
||||||
source: {
|
source: {
|
||||||
excludeDecorators: true,
|
excludeDecorators: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
};
|
||||||
export const tags = ["autodocs"];
|
export const tags = ['autodocs'];
|
||||||
|
|||||||
@@ -8,4 +8,4 @@ const PRName = function () {
|
|||||||
return 'PR-'+ID;
|
return 'PR-'+ID;
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log(PRName());
|
console.log(PRName());
|
||||||
|
|||||||
142
bin/cli.js
142
bin/cli.js
@@ -2,62 +2,62 @@
|
|||||||
const { execSync } = require('child_process');
|
const { execSync } = require('child_process');
|
||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
|
|
||||||
const isWin = process.platform === "win32";
|
const isWin = process.platform === 'win32';
|
||||||
|
|
||||||
const runCommand = command => {
|
const runCommand = command => {
|
||||||
try{
|
try{
|
||||||
execSync(`${command}`, {stdio: 'inherit'});
|
execSync(`${command}`, {stdio: 'inherit'});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(`Failed to execute ${command}`, e);
|
console.error(`Failed to execute ${command}`, e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
};
|
||||||
|
|
||||||
const runCommandWithOutput = command => {
|
const runCommandWithOutput = command => {
|
||||||
try{
|
try{
|
||||||
return execSync(`${command}`);
|
return execSync(`${command}`);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(`Failed to execute ${command}`, e);
|
console.error(`Failed to execute ${command}`, e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
const replaceTextOnFile = ({
|
const replaceTextOnFile = ({
|
||||||
file,
|
file,
|
||||||
textToBeReplaced,
|
textToBeReplaced,
|
||||||
textReplace,
|
textReplace,
|
||||||
arrOfObjectsBeReplaced
|
arrOfObjectsBeReplaced
|
||||||
}) => {
|
}) => {
|
||||||
let data
|
let data;
|
||||||
try{
|
try{
|
||||||
data = fs.readFileSync(file, 'utf8');
|
data = fs.readFileSync(file, 'utf8');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(`Failed to read file ${file}`, e);
|
console.error(`Failed to read file ${file}`, e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let result
|
let result;
|
||||||
if(arrOfObjectsBeReplaced){
|
if(arrOfObjectsBeReplaced){
|
||||||
arrOfObjectsBeReplaced.forEach( obj => {
|
arrOfObjectsBeReplaced.forEach( obj => {
|
||||||
if(result){
|
if(result){
|
||||||
result = result.replace(obj.textToBeReplaced, obj.textReplace).replace(/^\s*[\r\n]/gm, ' ');
|
result = result.replace(obj.textToBeReplaced, obj.textReplace).replace(/^\s*[\r\n]/gm, ' ');
|
||||||
}else{
|
}else{
|
||||||
result = data.replace(obj.textToBeReplaced, obj.textReplace).replace(/^\s*[\r\n]/gm, ' ');
|
result = data.replace(obj.textToBeReplaced, obj.textReplace).replace(/^\s*[\r\n]/gm, ' ');
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
}else{
|
}else{
|
||||||
result = data.replace(textToBeReplaced, textReplace).replace(/^\s*[\r\n]/gm, ' ');
|
result = data.replace(textToBeReplaced, textReplace).replace(/^\s*[\r\n]/gm, ' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
try{
|
try{
|
||||||
console.log('text changed')
|
console.log('text changed');
|
||||||
fs.writeFileSync(file, result, 'utf8');
|
fs.writeFileSync(file, result, 'utf8');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(`Failed to read file ${file}`, e);
|
console.error(`Failed to read file ${file}`, e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
const repoName = process.argv[2];
|
const repoName = process.argv[2];
|
||||||
const gitCheckoutCommand = `git clone --depth 1 https://github.com/aleleba/create-react-component-library ${repoName}`;
|
const gitCheckoutCommand = `git clone --depth 1 https://github.com/aleleba/create-react-component-library ${repoName}`;
|
||||||
@@ -65,13 +65,13 @@ console.log(`Cloning the repository with name ${repoName}`);
|
|||||||
const checkedOut = runCommand(gitCheckoutCommand);
|
const checkedOut = runCommand(gitCheckoutCommand);
|
||||||
if(!checkedOut) process.exit(-1);
|
if(!checkedOut) process.exit(-1);
|
||||||
|
|
||||||
const actualVersion = runCommandWithOutput(`cd ${repoName} && node -p "require('./package.json').version"`).toString().trim()
|
const actualVersion = runCommandWithOutput(`cd ${repoName} && node -p "require('./package.json').version"`).toString().trim();
|
||||||
|
|
||||||
const installDepsCommand = `cd ${repoName} && npm i`;
|
const installDepsCommand = `cd ${repoName} && npm i`;
|
||||||
const cleanGitHistoryCommand = `cd ${repoName} && rm -rf .git && git init && git add --all -- ":!.github" ":!bin" && git commit -m "Initial commit"`
|
const cleanGitHistoryCommand = `cd ${repoName} && rm -rf .git && git init && git add --all -- ":!.github" ":!bin" && git commit -m "Initial commit"`;
|
||||||
const cleanGitHistoryCommandWindows = `cd ${repoName} && rmdir .git /s /q && git init && git add --all -- ":!.github" ":!bin" && git commit -m "Initial commit"`
|
const cleanGitHistoryCommandWindows = `cd ${repoName} && rmdir .git /s /q && git init && git add --all -- ":!.github" ":!bin" && git commit -m "Initial commit"`;
|
||||||
const deleteFoldersCommand = `cd ${repoName} && rm -rf .github && rm -rf bin`
|
const deleteFoldersCommand = `cd ${repoName} && rm -rf .github && rm -rf bin`;
|
||||||
const deleteFoldersCommandWindows = `cd ${repoName} && rmdir .github /s /q && rmdir bin /s /q`
|
const deleteFoldersCommandWindows = `cd ${repoName} && rmdir .github /s /q && rmdir bin /s /q`;
|
||||||
|
|
||||||
console.log(`Installing dependencies for ${repoName}`);
|
console.log(`Installing dependencies for ${repoName}`);
|
||||||
const installedDeps = runCommand(installDepsCommand);
|
const installedDeps = runCommand(installDepsCommand);
|
||||||
@@ -79,31 +79,31 @@ if(!installedDeps) process.exit(-1);
|
|||||||
|
|
||||||
console.log(`Replacing Json data for ${repoName}`);
|
console.log(`Replacing Json data for ${repoName}`);
|
||||||
replaceTextOnFile({
|
replaceTextOnFile({
|
||||||
file: `./${repoName}/package.json`,
|
file: `./${repoName}/package.json`,
|
||||||
arrOfObjectsBeReplaced: [
|
arrOfObjectsBeReplaced: [
|
||||||
{
|
{
|
||||||
textToBeReplaced: `"bin": "./bin/cli.js",`,
|
textToBeReplaced: '"bin": "./bin/cli.js",',
|
||||||
textReplace: ``
|
textReplace: ''
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
textToBeReplaced: `"version": "${actualVersion}",`,
|
textToBeReplaced: `"version": "${actualVersion}",`,
|
||||||
textReplace: `"version": "0.0.1",`
|
textReplace: '"version": "0.0.1",'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
textToBeReplaced: `"name": "@aleleba/create-react-component-library",`,
|
textToBeReplaced: '"name": "@aleleba/create-react-component-library",',
|
||||||
textReplace: `"name": "${repoName}",`
|
textReplace: `"name": "${repoName}",`
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
})
|
});
|
||||||
|
|
||||||
console.log(`Cleaning History of Git for ${repoName}`);
|
console.log(`Cleaning History of Git for ${repoName}`);
|
||||||
const cleanGitHistory = isWin ? runCommand(cleanGitHistoryCommandWindows) : runCommand(cleanGitHistoryCommand);
|
const cleanGitHistory = isWin ? runCommand(cleanGitHistoryCommandWindows) : runCommand(cleanGitHistoryCommand);
|
||||||
if(!cleanGitHistory) process.exit(-1);
|
if(!cleanGitHistory) process.exit(-1);
|
||||||
|
|
||||||
console.log("Congratulations! You are ready. Follow the following commands to start");
|
console.log('Congratulations! You are ready. Follow the following commands to start');
|
||||||
console.log(`cd ${repoName}`);
|
console.log(`cd ${repoName}`);
|
||||||
console.log('Create a .env file with LIBRARY_NAME=your_library_name(default: ui-library), External_CSS (optional)(Default: false), EXTERNAL_CSS_NAME=(optional)(Default: index.css)');
|
console.log('Create a .env file with LIBRARY_NAME=your_library_name(default: ui-library), External_CSS (optional)(Default: false), EXTERNAL_CSS_NAME=(optional)(Default: index.css)');
|
||||||
console.log(`Then you can run: npm start`);
|
console.log('Then you can run: npm start');
|
||||||
|
|
||||||
const deleteFolders = isWin ? runCommand(deleteFoldersCommandWindows) : runCommand(deleteFoldersCommand);
|
const deleteFolders = isWin ? runCommand(deleteFoldersCommandWindows) : runCommand(deleteFoldersCommand);
|
||||||
if(!deleteFolders) process.exit(-1);
|
if(!deleteFolders) process.exit(-1);
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
import { defineConfig } from "cypress";
|
import { defineConfig } from 'cypress';
|
||||||
import webpackConfig from './webpack.cy.config';
|
import webpackConfig from './webpack.cy.config';
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
component: {
|
component: {
|
||||||
specPattern: 'src/**/*.cy.{js,jsx,ts,tsx}',
|
specPattern: 'src/**/*.cy.{js,jsx,ts,tsx}',
|
||||||
devServer: {
|
devServer: {
|
||||||
framework: "react",
|
framework: 'react',
|
||||||
bundler: "webpack",
|
bundler: 'webpack',
|
||||||
webpackConfig: webpackConfig,
|
webpackConfig: webpackConfig,
|
||||||
},
|
},
|
||||||
viewportWidth: 1280,
|
viewportWidth: 1280,
|
||||||
viewportHeight: 720,
|
viewportHeight: 720,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -34,4 +34,4 @@
|
|||||||
// visit(originalFn: CommandOriginalFn, url: string, options: Partial<VisitOptions>): Chainable<Element>
|
// visit(originalFn: CommandOriginalFn, url: string, options: Partial<VisitOptions>): Chainable<Element>
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|||||||
@@ -15,16 +15,17 @@
|
|||||||
// ***********************************************************
|
// ***********************************************************
|
||||||
|
|
||||||
// Import commands.js using ES2015 syntax:
|
// Import commands.js using ES2015 syntax:
|
||||||
import './commands'
|
import './commands';
|
||||||
|
|
||||||
// Alternatively you can use CommonJS syntax:
|
// Alternatively you can use CommonJS syntax:
|
||||||
// require('./commands')
|
// require('./commands')
|
||||||
|
|
||||||
import { mount } from 'cypress/react'
|
import { mount } from 'cypress/react';
|
||||||
|
|
||||||
// Augment the Cypress namespace to include type definitions for
|
// Augment the Cypress namespace to include type definitions for
|
||||||
// your custom command.
|
// your custom command.
|
||||||
declare global {
|
declare global {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-namespace
|
||||||
namespace Cypress {
|
namespace Cypress {
|
||||||
interface Chainable {
|
interface Chainable {
|
||||||
mount: typeof mount
|
mount: typeof mount
|
||||||
@@ -32,7 +33,7 @@ declare global {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Cypress.Commands.add('mount', mount)
|
Cypress.Commands.add('mount', mount);
|
||||||
|
|
||||||
// Example use:
|
// Example use:
|
||||||
// cy.mount(<MyComponent />)
|
// cy.mount(<MyComponent />)
|
||||||
|
|||||||
50
eslint.config.mjs
Normal file
50
eslint.config.mjs
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
import js from '@eslint/js';
|
||||||
|
import tseslint from 'typescript-eslint';
|
||||||
|
import react from 'eslint-plugin-react';
|
||||||
|
import storybook from 'eslint-plugin-storybook';
|
||||||
|
import globals from 'globals';
|
||||||
|
|
||||||
|
export default tseslint.config(
|
||||||
|
{
|
||||||
|
ignores: ['node_modules/**', 'dist/**', 'build/**', 'storybook-static/**'],
|
||||||
|
},
|
||||||
|
js.configs.recommended,
|
||||||
|
...tseslint.configs.recommended,
|
||||||
|
react.configs.flat.recommended,
|
||||||
|
react.configs.flat['jsx-runtime'],
|
||||||
|
...storybook.configs['flat/recommended'],
|
||||||
|
{
|
||||||
|
settings: {
|
||||||
|
react: { version: 'detect' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: ['**/*.{js,jsx,ts,tsx}'],
|
||||||
|
languageOptions: {
|
||||||
|
ecmaVersion: 'latest',
|
||||||
|
sourceType: 'module',
|
||||||
|
parserOptions: {
|
||||||
|
ecmaFeatures: { jsx: true },
|
||||||
|
},
|
||||||
|
globals: {
|
||||||
|
...globals.browser,
|
||||||
|
...globals.node,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
indent: ['error', 'tab'],
|
||||||
|
'linebreak-style': ['error', 'unix'],
|
||||||
|
quotes: ['error', 'single'],
|
||||||
|
semi: ['error', 'always'],
|
||||||
|
'eol-last': ['error', 'always'],
|
||||||
|
'react/prop-types': 'off',
|
||||||
|
'@typescript-eslint/no-require-imports': 'off',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: ['**/*.js'],
|
||||||
|
languageOptions: {
|
||||||
|
sourceType: 'commonjs',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
@@ -6,12 +6,12 @@ const aliases = pathsToModuleNameMapper(compilerOptions.paths, {
|
|||||||
});
|
});
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
setupFilesAfterEnv: ['<rootDir>/setupTest.ts'],
|
setupFilesAfterEnv: ['<rootDir>/setupTest.ts'],
|
||||||
testPathIgnorePatterns: ['/node_modules/', '\\.cy.(js|jsx|ts|tsx)$'],
|
testPathIgnorePatterns: ['/node_modules/', '\\.cy.(js|jsx|ts|tsx)$'],
|
||||||
testEnvironment: 'jsdom',
|
testEnvironment: 'jsdom',
|
||||||
moduleNameMapper: {
|
moduleNameMapper: {
|
||||||
...aliases,
|
...aliases,
|
||||||
'\\.(jpg|ico|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': '<rootDir>/src/__mocks__/fileMock.ts',
|
'\\.(jpg|ico|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': '<rootDir>/src/__mocks__/fileMock.ts',
|
||||||
'\\.(css|sass|scss|less)$': 'identity-obj-proxy'
|
'\\.(css|sass|scss|less)$': 'identity-obj-proxy'
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
5316
package-lock.json
generated
5316
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
81
package.json
81
package.json
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@aleleba/create-react-component-library",
|
"name": "@aleleba/create-react-component-library",
|
||||||
"version": "1.3.2",
|
"version": "1.4.0",
|
||||||
"description": "A starter kit for create a React component Library with storybook",
|
"description": "A starter kit for create a React component Library with storybook",
|
||||||
"bin": "./bin/cli.js",
|
"bin": "./bin/cli.js",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
@@ -16,8 +16,8 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "npm run storybook",
|
"start": "npm run storybook",
|
||||||
"build": "webpack",
|
"build": "webpack",
|
||||||
"lint": "eslint ./ --ext .js --ext .ts --ext .jsx --ext .tsx",
|
"lint": "eslint .",
|
||||||
"lint:fix": "eslint ./ --ext .js --ext .ts --ext .jsx --ext .tsx --fix",
|
"lint:fix": "eslint . --fix",
|
||||||
"test": "jest",
|
"test": "jest",
|
||||||
"test:watch": "jest --watch",
|
"test:watch": "jest --watch",
|
||||||
"storybook": "storybook dev -p 3000",
|
"storybook": "storybook dev -p 3000",
|
||||||
@@ -44,59 +44,62 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/aleleba/create-react-component-library#readme",
|
"homepage": "https://github.com/aleleba/create-react-component-library#readme",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.28.6",
|
"@babel/core": "^7.29.7",
|
||||||
"@babel/preset-env": "^7.28.6",
|
"@babel/preset-env": "^7.29.7",
|
||||||
"@babel/preset-react": "^7.28.5",
|
"@babel/preset-react": "^7.29.7",
|
||||||
"@babel/preset-typescript": "^7.28.5",
|
"@babel/preset-typescript": "^7.29.7",
|
||||||
"@babel/register": "^7.28.6",
|
"@babel/register": "^7.29.7",
|
||||||
|
"@eslint/js": "^9.39.4",
|
||||||
"@mdx-js/react": "^3.1.1",
|
"@mdx-js/react": "^3.1.1",
|
||||||
"@storybook/addon-docs": "^10.2.1",
|
"@storybook/addon-docs": "^10.4.3",
|
||||||
"@storybook/addon-links": "^10.2.1",
|
"@storybook/addon-links": "^10.4.3",
|
||||||
"@storybook/addon-styling-webpack": "^3.0.0",
|
"@storybook/addon-styling-webpack": "^3.0.2",
|
||||||
"@storybook/addon-webpack5-compiler-babel": "^4.0.0",
|
"@storybook/addon-webpack5-compiler-babel": "^4.0.1",
|
||||||
"@storybook/cli": "^10.2.1",
|
"@storybook/cli": "^10.4.3",
|
||||||
"@storybook/preset-scss": "^1.0.3",
|
"@storybook/preset-scss": "^1.0.3",
|
||||||
"@storybook/react-webpack5": "^10.2.1",
|
"@storybook/react-webpack5": "^10.4.3",
|
||||||
"@testing-library/dom": "^10.4.1",
|
"@testing-library/dom": "^10.4.1",
|
||||||
"@testing-library/jest-dom": "^6.9.1",
|
"@testing-library/jest-dom": "^6.9.1",
|
||||||
"@testing-library/react": "^16.3.2",
|
"@testing-library/react": "^16.3.2",
|
||||||
"@testing-library/user-event": "^14.6.1",
|
"@testing-library/user-event": "^14.6.1",
|
||||||
"@types/jest": "^30.0.0",
|
"@types/jest": "^30.0.0",
|
||||||
"@types/node": "^25.0.10",
|
"@types/node": "^25.9.2",
|
||||||
"@types/react": "^19.2.10",
|
"@types/react": "^19.2.17",
|
||||||
"@types/react-dom": "^19.2.3",
|
"@types/react-dom": "^19.2.3",
|
||||||
"@types/webpack": "^5.28.5",
|
"@types/webpack": "^5.28.5",
|
||||||
"babel-loader": "^10.0.0",
|
"babel-loader": "^10.1.1",
|
||||||
"clean-webpack-plugin": "^4.0.0",
|
"clean-webpack-plugin": "^4.0.0",
|
||||||
"css-loader": "^7.1.3",
|
"css-loader": "^7.1.4",
|
||||||
"css-minimizer-webpack-plugin": "^7.0.4",
|
"css-minimizer-webpack-plugin": "^8.0.0",
|
||||||
"cypress": "^15.9.0",
|
"cypress": "^15.17.0",
|
||||||
"dotenv": "^17.2.3",
|
"dotenv": "^17.4.2",
|
||||||
"eslint": "^9.39.2",
|
"eslint": "^9.39.4",
|
||||||
"eslint-plugin-react": "^7.37.5",
|
"eslint-plugin-react": "^7.37.5",
|
||||||
"eslint-plugin-storybook": "^10.2.1",
|
"eslint-plugin-storybook": "^10.4.3",
|
||||||
"eslint-webpack-plugin": "^5.0.2",
|
"eslint-webpack-plugin": "^6.0.0",
|
||||||
"html-webpack-plugin": "^5.6.6",
|
"globals": "^16.5.0",
|
||||||
|
"html-webpack-plugin": "^5.6.7",
|
||||||
"identity-obj-proxy": "^3.0.0",
|
"identity-obj-proxy": "^3.0.0",
|
||||||
"jest": "^30.2.0",
|
"jest": "^30.4.2",
|
||||||
"jest-environment-jsdom": "^30.2.0",
|
"jest-environment-jsdom": "^30.4.1",
|
||||||
"jest-fetch-mock": "^3.0.3",
|
"jest-fetch-mock": "^3.0.3",
|
||||||
"mini-css-extract-plugin": "^2.10.0",
|
"mini-css-extract-plugin": "^2.10.2",
|
||||||
"react": "^19.2.4",
|
"react": "^19.2.7",
|
||||||
"react-dom": "^19.2.4",
|
"react-dom": "^19.2.7",
|
||||||
"resolve-ts-aliases": "^1.0.1",
|
"resolve-ts-aliases": "^1.0.1",
|
||||||
"sass": "^1.97.3",
|
"sass": "^1.100.0",
|
||||||
"sass-loader": "^16.0.6",
|
"sass-loader": "^17.0.0",
|
||||||
"storybook": "^10.2.1",
|
"storybook": "^10.4.3",
|
||||||
"style-loader": "^4.0.0",
|
"style-loader": "^4.0.0",
|
||||||
"terser-webpack-plugin": "^5.3.16",
|
"terser-webpack-plugin": "^5.6.1",
|
||||||
"ts-jest": "^29.4.6",
|
"ts-jest": "^29.4.11",
|
||||||
"ts-loader": "^9.5.4",
|
"ts-loader": "^9.6.0",
|
||||||
"tsconfig-paths-webpack-plugin": "^4.2.0",
|
"tsconfig-paths-webpack-plugin": "^4.2.0",
|
||||||
"typescript": "^5.9.3",
|
"typescript": "^6.0.3",
|
||||||
|
"typescript-eslint": "^8.61.0",
|
||||||
"url-loader": "^4.1.1",
|
"url-loader": "^4.1.1",
|
||||||
"webpack": "^5.104.1",
|
"webpack": "^5.107.2",
|
||||||
"webpack-cli": "^6.0.1",
|
"webpack-cli": "^7.0.3",
|
||||||
"webpack-node-externals": "^3.0.0"
|
"webpack-node-externals": "^3.0.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
|
|||||||
14
setupTest.ts
14
setupTest.ts
@@ -5,16 +5,16 @@
|
|||||||
import '@testing-library/jest-dom';
|
import '@testing-library/jest-dom';
|
||||||
|
|
||||||
//import fetch Mock
|
//import fetch Mock
|
||||||
import fetchMock from "jest-fetch-mock";
|
import fetchMock from 'jest-fetch-mock';
|
||||||
fetchMock.enableMocks();
|
fetchMock.enableMocks();
|
||||||
|
|
||||||
//Fixing Pollyfill for react-slick
|
//Fixing Pollyfill for react-slick
|
||||||
window.matchMedia =
|
window.matchMedia =
|
||||||
window.matchMedia ||
|
window.matchMedia ||
|
||||||
function() {
|
function() {
|
||||||
return {
|
return {
|
||||||
matches: false,
|
matches: false,
|
||||||
addListener: function() {},
|
addListener: function() {},
|
||||||
removeListener: function() {}
|
removeListener: function() {}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
11
src/@types/custom.d.ts
vendored
11
src/@types/custom.d.ts
vendored
@@ -1,8 +1,13 @@
|
|||||||
declare module "*.svg" {
|
declare module '*.svg' {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
const content: any;
|
const content: any;
|
||||||
export default content;
|
export default content;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare module "@storybook/react" {
|
declare module '*.scss';
|
||||||
export * from "@storybook/react/dist/index";
|
declare module '*.sass';
|
||||||
|
declare module '*.css';
|
||||||
|
|
||||||
|
declare module '@storybook/react' {
|
||||||
|
export * from '@storybook/react/dist/index';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
module.exports = '';
|
module.exports = '';
|
||||||
|
|||||||
@@ -1,28 +1,27 @@
|
|||||||
import React from 'react';
|
import type { Meta, StoryObj } from '@storybook/react-webpack5';
|
||||||
import type { Meta, StoryObj } from '@storybook/react';
|
|
||||||
import { Card } from '@components';
|
import { Card } from '@components';
|
||||||
|
|
||||||
// More on default export: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
|
// More on default export: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
|
||||||
const meta: Meta<typeof Card> = {
|
const meta: Meta<typeof Card> = {
|
||||||
title: 'Example/Card',
|
title: 'Example/Card',
|
||||||
component: Card,
|
component: Card,
|
||||||
parameters: {
|
parameters: {
|
||||||
docs: {
|
docs: {
|
||||||
description: {
|
description: {
|
||||||
component: 'A reusable Card component for displaying content with an optional title.',
|
component: 'A reusable Card component for displaying content with an optional title.',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
argTypes: {
|
argTypes: {
|
||||||
title: {
|
title: {
|
||||||
control: 'text',
|
control: 'text',
|
||||||
description: 'The title of the card',
|
description: 'The title of the card',
|
||||||
},
|
},
|
||||||
children: {
|
children: {
|
||||||
control: false,
|
control: false,
|
||||||
description: 'The content to display inside the card',
|
description: 'The content to display inside the card',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default meta;
|
export default meta;
|
||||||
@@ -30,8 +29,8 @@ type Story = StoryObj<typeof meta>;
|
|||||||
|
|
||||||
// More on args: https://storybook.js.org/docs/react/writing-stories/args
|
// More on args: https://storybook.js.org/docs/react/writing-stories/args
|
||||||
export const Basic: Story = {
|
export const Basic: Story = {
|
||||||
args: {
|
args: {
|
||||||
title: 'Test Title',
|
title: 'Test Title',
|
||||||
children: <p>Test Content</p>,
|
children: <p>Test Content</p>,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React, { FC } from "react";
|
import React, { FC } from 'react';
|
||||||
import "./style.scss";
|
import './style.scss';
|
||||||
|
|
||||||
type TCardProps = {
|
type TCardProps = {
|
||||||
/**
|
/**
|
||||||
@@ -13,13 +13,13 @@ type TCardProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const Card: FC<TCardProps> = ({ title, children}) => {
|
const Card: FC<TCardProps> = ({ title, children}) => {
|
||||||
return (
|
return (
|
||||||
<div className="Card">
|
<div className="Card">
|
||||||
<div className="Title">{title}</div>
|
<div className="Title">{title}</div>
|
||||||
|
|
||||||
<div className="Content">{children}</div>
|
<div className="Content">{children}</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export { Card, TCardProps }
|
export { Card, TCardProps };
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
import React from 'react';
|
|
||||||
import { Card } from '@components';
|
import { Card } from '@components';
|
||||||
|
|
||||||
describe('Testing Card Component', () => {
|
describe('Testing Card Component', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
cy.mount(<Card title='Test Title'><p>Test Content</p></Card>);
|
cy.mount(<Card title='Test Title'><p>Test Content</p></Card>);
|
||||||
})
|
});
|
||||||
it('Show Title', () => {
|
it('Show Title', () => {
|
||||||
cy.get('div').contains('Test Title');
|
cy.get('div').contains('Test Title');
|
||||||
})
|
});
|
||||||
it('Show Child Component', () => {
|
it('Show Child Component', () => {
|
||||||
cy.get('p').contains('Test Content');
|
cy.get('p').contains('Test Content');
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
|
|||||||
@@ -1,24 +1,23 @@
|
|||||||
import React from 'react';
|
|
||||||
import { render, screen } from '@testing-library/react';
|
import { render, screen } from '@testing-library/react';
|
||||||
import { Card } from '@components';
|
import { Card } from '@components';
|
||||||
|
|
||||||
describe('<Card/> Component', () => {
|
describe('<Card/> Component', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
// fetchMock.resetMocks();
|
// fetchMock.resetMocks();
|
||||||
render(<Card title='Test Title'><p>Test Content</p></Card>)
|
render(<Card title='Test Title'><p>Test Content</p></Card>);
|
||||||
});
|
});
|
||||||
it('Show Title', async () => {
|
it('Show Title', async () => {
|
||||||
/* fetchMock.mockResponseOnce(JSON.stringify({
|
/* fetchMock.mockResponseOnce(JSON.stringify({
|
||||||
//First Data Fetch
|
//First Data Fetch
|
||||||
data: 'data'
|
data: 'data'
|
||||||
})); */
|
})); */
|
||||||
expect(screen.getByText('Test Title')).toBeInTheDocument();
|
expect(screen.getByText('Test Title')).toBeInTheDocument();
|
||||||
})
|
});
|
||||||
it('Show Child Component', async () => {
|
it('Show Child Component', async () => {
|
||||||
/* fetchMock.mockResponseOnce(JSON.stringify({
|
/* fetchMock.mockResponseOnce(JSON.stringify({
|
||||||
//First Data Fetch
|
//First Data Fetch
|
||||||
data: 'data'
|
data: 'data'
|
||||||
})); */
|
})); */
|
||||||
expect(screen.getByText('Test Content')).toBeInTheDocument();
|
expect(screen.getByText('Test Content')).toBeInTheDocument();
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
export * from './Card';
|
export * from './Card';
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
|
"ignoreDeprecations": "6.0",
|
||||||
"declaration": true,
|
"declaration": true,
|
||||||
"declarationDir": "./dist/types",
|
"declarationDir": "./dist/types",
|
||||||
|
"rootDir": "./src/components",
|
||||||
"target": "es5",
|
"target": "es5",
|
||||||
"lib": [
|
"lib": [
|
||||||
"dom",
|
"dom",
|
||||||
@@ -38,7 +40,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"."
|
"src/components",
|
||||||
|
"src/@types"
|
||||||
],
|
],
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"node_modules",
|
"node_modules",
|
||||||
|
|||||||
@@ -10,92 +10,92 @@ import ESLintPlugin from 'eslint-webpack-plugin';
|
|||||||
import { resolveTsAliases } from 'resolve-ts-aliases';
|
import { resolveTsAliases } from 'resolve-ts-aliases';
|
||||||
|
|
||||||
const dotEnvToParse = dotenv.config();
|
const dotEnvToParse = dotenv.config();
|
||||||
const libraryName = process.env.LIBRARY_NAME ? process.env.LIBRARY_NAME : "ui-library"
|
const libraryName = process.env.LIBRARY_NAME ? process.env.LIBRARY_NAME : 'ui-library';
|
||||||
const externalCss = process.env.EXTERNAL_CSS === 'true' ? true : false
|
const externalCss = process.env.EXTERNAL_CSS === 'true' ? true : false;
|
||||||
const externalCssName = process.env.EXTERNAL_CSS_NAME ? process.env.EXTERNAL_CSS_NAME : 'index.css'
|
const externalCssName = process.env.EXTERNAL_CSS_NAME ? process.env.EXTERNAL_CSS_NAME : 'index.css';
|
||||||
const alias = resolveTsAliases(path.resolve('tsconfig.json'));
|
const alias = resolveTsAliases(path.resolve('tsconfig.json'));
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
entry: './src/components/index.tsx',
|
entry: './src/components/index.tsx',
|
||||||
externals: [nodeExternals()],
|
externals: [nodeExternals()],
|
||||||
resolve: {
|
resolve: {
|
||||||
extensions: ['.js', '.jsx','.ts','.tsx', '.json'],
|
extensions: ['.js', '.jsx','.ts','.tsx', '.json'],
|
||||||
alias,
|
alias,
|
||||||
},
|
},
|
||||||
mode: 'production',
|
mode: 'production',
|
||||||
output: {
|
output: {
|
||||||
filename: 'index.js',
|
filename: 'index.js',
|
||||||
path: path.resolve(__dirname, 'dist'),
|
path: path.resolve(__dirname, 'dist'),
|
||||||
library: libraryName,
|
library: libraryName,
|
||||||
libraryTarget: 'umd',
|
libraryTarget: 'umd',
|
||||||
globalObject: 'this',
|
globalObject: 'this',
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
new CleanWebpackPlugin(),
|
new CleanWebpackPlugin(),
|
||||||
...(externalCss === true ? [
|
...(externalCss === true ? [
|
||||||
new MiniCssExtractPlugin({
|
new MiniCssExtractPlugin({
|
||||||
filename: externalCssName,
|
filename: externalCssName,
|
||||||
}),
|
}),
|
||||||
] : []),
|
] : []),
|
||||||
new webpack.DefinePlugin({
|
new webpack.DefinePlugin({
|
||||||
'process.env': JSON.stringify(dotEnvToParse.parsed),
|
'process.env': JSON.stringify(dotEnvToParse.parsed),
|
||||||
}),
|
}),
|
||||||
new ESLintPlugin(),
|
new ESLintPlugin(),
|
||||||
],
|
],
|
||||||
module: {
|
module: {
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
test: /\.(ts|tsx)$/,
|
test: /\.(ts|tsx)$/,
|
||||||
exclude: [/node_modules/, /\.test\.(ts|tsx)$/, /\.cy\.(ts|tsx)$/],
|
exclude: [/node_modules/, /\.test\.(ts|tsx)$/, /\.cy\.(ts|tsx)$/],
|
||||||
use: {
|
use: {
|
||||||
loader: 'ts-loader',
|
loader: 'ts-loader',
|
||||||
options: {
|
|
||||||
onlyCompileBundledFiles: true,
|
|
||||||
compilerOptions: {
|
|
||||||
noEmit: false,
|
|
||||||
declaration: true,
|
|
||||||
declarationDir: './dist/types'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.(js|jsx)$/,
|
|
||||||
exclude: /node_modules/,
|
|
||||||
use: 'babel-loader',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.(css|sass|scss)$/,
|
|
||||||
use: [
|
|
||||||
externalCss === true ? MiniCssExtractPlugin.loader : 'style-loader',
|
|
||||||
{
|
|
||||||
loader: 'css-loader',
|
|
||||||
options: {
|
options: {
|
||||||
modules: {
|
onlyCompileBundledFiles: true,
|
||||||
namedExport: false,
|
compilerOptions: {
|
||||||
exportLocalsConvention: 'as-is',
|
noEmit: false,
|
||||||
auto: /\.module\.\w+$/i,
|
declaration: true,
|
||||||
|
declarationDir: './dist/types'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
},
|
},
|
||||||
'sass-loader',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.(ttf|otf|eot|woff|woff2)$/,
|
|
||||||
loader: 'url-loader',
|
|
||||||
options: {
|
|
||||||
name: 'assets/fonts/[name].[ext]',
|
|
||||||
esModule: false,
|
|
||||||
},
|
},
|
||||||
},
|
{
|
||||||
]
|
test: /\.(js|jsx)$/,
|
||||||
},
|
exclude: /node_modules/,
|
||||||
optimization: {
|
use: 'babel-loader',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.(css|sass|scss)$/,
|
||||||
|
use: [
|
||||||
|
externalCss === true ? MiniCssExtractPlugin.loader : 'style-loader',
|
||||||
|
{
|
||||||
|
loader: 'css-loader',
|
||||||
|
options: {
|
||||||
|
modules: {
|
||||||
|
namedExport: false,
|
||||||
|
exportLocalsConvention: 'as-is',
|
||||||
|
auto: /\.module\.\w+$/i,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'sass-loader',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.(ttf|otf|eot|woff|woff2)$/,
|
||||||
|
loader: 'url-loader',
|
||||||
|
options: {
|
||||||
|
name: 'assets/fonts/[name].[ext]',
|
||||||
|
esModule: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
optimization: {
|
||||||
minimize: true,
|
minimize: true,
|
||||||
minimizer: [
|
minimizer: [
|
||||||
new CssMinimizerPlugin(),
|
new CssMinimizerPlugin(),
|
||||||
new TerserPlugin(),
|
new TerserPlugin(),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -10,83 +10,83 @@ import ESLintPlugin from 'eslint-webpack-plugin';
|
|||||||
import { resolveTsAliases } from 'resolve-ts-aliases';
|
import { resolveTsAliases } from 'resolve-ts-aliases';
|
||||||
|
|
||||||
const dotEnvToParse = dotenv.config();
|
const dotEnvToParse = dotenv.config();
|
||||||
const externalCss = process.env.EXTERNAL_CSS === 'true' ? true : false
|
const externalCss = process.env.EXTERNAL_CSS === 'true' ? true : false;
|
||||||
const externalCssName = process.env.EXTERNAL_CSS_NAME ? process.env.EXTERNAL_CSS_NAME : 'index.css'
|
const externalCssName = process.env.EXTERNAL_CSS_NAME ? process.env.EXTERNAL_CSS_NAME : 'index.css';
|
||||||
const alias = resolveTsAliases(path.resolve('tsconfig.json'));
|
const alias = resolveTsAliases(path.resolve('tsconfig.json'));
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
entry: './src/components/index.tsx',
|
entry: './src/components/index.tsx',
|
||||||
resolve: {
|
resolve: {
|
||||||
extensions: ['.js', '.jsx','.ts','.tsx', '.json'],
|
extensions: ['.js', '.jsx','.ts','.tsx', '.json'],
|
||||||
alias,
|
alias,
|
||||||
},
|
},
|
||||||
mode: 'development',
|
mode: 'development',
|
||||||
output: {
|
output: {
|
||||||
path: path.resolve(__dirname, 'dist'),
|
path: path.resolve(__dirname, 'dist'),
|
||||||
},
|
},
|
||||||
target: 'web',
|
target: 'web',
|
||||||
plugins: [
|
plugins: [
|
||||||
new CleanWebpackPlugin(),
|
new CleanWebpackPlugin(),
|
||||||
...(externalCss === true ? [
|
...(externalCss === true ? [
|
||||||
new MiniCssExtractPlugin({
|
new MiniCssExtractPlugin({
|
||||||
filename: externalCssName,
|
filename: externalCssName,
|
||||||
}),
|
}),
|
||||||
] : []),
|
] : []),
|
||||||
new webpack.DefinePlugin({
|
new webpack.DefinePlugin({
|
||||||
'process.env': JSON.stringify(dotEnvToParse.parsed),
|
'process.env': JSON.stringify(dotEnvToParse.parsed),
|
||||||
}),
|
}),
|
||||||
new ESLintPlugin(),
|
new ESLintPlugin(),
|
||||||
new HtmlWebpackPlugin({
|
new HtmlWebpackPlugin({
|
||||||
template: path.join(__dirname, 'public', 'index.html'),
|
template: path.join(__dirname, 'public', 'index.html'),
|
||||||
}),
|
}),
|
||||||
new webpack.ProvidePlugin({
|
new webpack.ProvidePlugin({
|
||||||
React: 'react',
|
React: 'react',
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
module: {
|
module: {
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
test: /\.(ts|tsx)$/,
|
test: /\.(ts|tsx)$/,
|
||||||
exclude: /node_modules/,
|
exclude: /node_modules/,
|
||||||
use: 'ts-loader',
|
use: 'ts-loader',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /\.(js|jsx)$/,
|
test: /\.(js|jsx)$/,
|
||||||
exclude: /node_modules/,
|
exclude: /node_modules/,
|
||||||
use: 'babel-loader',
|
use: 'babel-loader',
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.(css|sass|scss)$/,
|
|
||||||
use: [
|
|
||||||
externalCss === true ? MiniCssExtractPlugin.loader : 'style-loader',
|
|
||||||
{
|
|
||||||
loader: 'css-loader',
|
|
||||||
options: {
|
|
||||||
modules: {
|
|
||||||
namedExport: false,
|
|
||||||
exportLocalsConvention: 'as-is',
|
|
||||||
auto: /\.module\.\w+$/i,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'sass-loader',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.(ttf|otf|eot|woff|woff2)$/,
|
|
||||||
loader: 'url-loader',
|
|
||||||
options: {
|
|
||||||
name: 'assets/fonts/[name].[ext]',
|
|
||||||
esModule: false,
|
|
||||||
},
|
},
|
||||||
},
|
{
|
||||||
]
|
test: /\.(css|sass|scss)$/,
|
||||||
},
|
use: [
|
||||||
optimization: {
|
externalCss === true ? MiniCssExtractPlugin.loader : 'style-loader',
|
||||||
|
{
|
||||||
|
loader: 'css-loader',
|
||||||
|
options: {
|
||||||
|
modules: {
|
||||||
|
namedExport: false,
|
||||||
|
exportLocalsConvention: 'as-is',
|
||||||
|
auto: /\.module\.\w+$/i,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'sass-loader',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.(ttf|otf|eot|woff|woff2)$/,
|
||||||
|
loader: 'url-loader',
|
||||||
|
options: {
|
||||||
|
name: 'assets/fonts/[name].[ext]',
|
||||||
|
esModule: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
optimization: {
|
||||||
minimize: true,
|
minimize: true,
|
||||||
minimizer: [
|
minimizer: [
|
||||||
new CssMinimizerPlugin(),
|
new CssMinimizerPlugin(),
|
||||||
new TerserPlugin(),
|
new TerserPlugin(),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
}
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user