Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[#88] Change Webpack to Vite #117

Merged
merged 25 commits into from
Jan 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
a961344
[#88] Add the vite-template folder with a working cra app migrated to…
malparty Jul 21, 2022
12e8579
[#88] Add the initializeViteApp to the cli-tool package
malparty Jul 21, 2022
922a22f
[#88] Update README instructions and example command
malparty Jul 22, 2022
a82f6a1
[#88] Fix Jest tests not running
malparty Jul 22, 2022
abadc8a
[#88] Refactor to ask for Vite or Webpack
malparty Jul 25, 2022
54c8bcc
[#88] Update test to use Vite instead of CRA
malparty Jul 25, 2022
40f2fff
[#88] Move vite-template outside from the lerna packages folder
malparty Jul 25, 2022
648ab00
[#88] Fix args for tests with Vite
malparty Jul 25, 2022
1d6c89e
[#88] Lint code and add logs to tests
malparty Jul 26, 2022
b22fced
[##88] Add the missing .github and .gitlab folders
malparty Jul 29, 2022
6d6f8ca
[#88] Re-enable CRA tests
malparty Jul 29, 2022
01c60ce
[#88] Fix cra test template path
malparty Jul 29, 2022
dab0edd
[#88] Fix README.md typo
malparty Jul 29, 2022
fb9e28c
[#88] Update vite README.md
malparty Jul 29, 2022
efa56f6
[#88] Remove last itteration of Create-React-App from the Vite template
malparty Jul 29, 2022
4129af6
[#88] Use relative path for tests so it work in both CI and local
malparty Jul 29, 2022
c7fc71a
[#88] Fix missing import in the bootstrap scss index
malparty Aug 3, 2022
1742bce
[#88] Fix local cra webpack not working
malparty Aug 3, 2022
f17b325
[#88] Fix cli-tool tests
malparty Aug 4, 2022
8999c21
[#88] Fix typo
malparty Aug 18, 2022
bb5c58b
[#88] Rename const to more generic name
malparty Aug 18, 2022
0aac8fc
[#88] Add .idea to .gitignore
malparty Aug 18, 2022
2efd4b5
[#88] Move download repository into a helper function
malparty Aug 18, 2022
ca7ea8c
[#88] Add template option to secure tailwind alternatives
malparty Aug 19, 2022
011dc9a
Fix broken tests
malparty Aug 19, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ npm-debug.log*

# editors
.vscode
.idea
28 changes: 22 additions & 6 deletions packages/cli-tool/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,24 @@ To run the CLI on your local machine:

> πŸ’‘ Running just `./bin/dev` without argument will display all the possible commands as well as additional information.

If your changes also impacted the `cra-template` package, you can still test them locally using:

```BASH
./bin/dev generate test-cli file:../cra-template
```
To test with local changes in either the `./packages/cra-template` or the `./vite-temaplte/` folders, use the following commands:
- For Vite:
```BASH
# Assuming the repository `react-temapltes` is in `~/Documents/Source/`.
# The generated app will be in `~/Documents/Source/vite-app`
./bin/dev generate vite-app ~/Documents/Source/ feature/gh88-replace-webpack-with-vite
```
- For Create React App (Webpack):
```BASH
# Assuming the repository `react-temapltes` is in `~/Documents/Source/`.
# The generated app will be in `~/Documents/Source/webpack-app`
./bin/dev generate webpack-app ~/Documents/Source/ file:react-templates/packages/cra-template
```

The last argument is named `templateReference` and is either the branch name (for Vite) or the local repository path (for CRA), relative to the previous argument.
The second argument (`~/Documents/Source`) enables to deploy the app in another directory rather than the current repository.

> Errors might occur if you try to generate a project within this repository.

Find more the [OCLIF Documentation](https://oclif.io/docs/introduction.html)!

Expand Down Expand Up @@ -123,8 +136,11 @@ It is free software and may be redistributed under the terms specified in the [L

This project is maintained and funded by [Nimble](https://nimblehq.co).

We love open source and do our part in sharing our work with the community!
We ❀️ open source and do our part in sharing our work with the community!
See [our other projects][community] or [hire our team][hire] to help build your product.

Want to join? [Check out our jobs][jobs]!

[community]: https://github.com/nimblehq
[hire]: https://nimblehq.co/
[jobs]: https://jobs.nimblehq.co/
10 changes: 5 additions & 5 deletions packages/cli-tool/src/add-ons/ui-framework/bootstrap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ const DEV_DEPENDENCIES = ['bootstrap@^5.1.3'];

export const addBootstrapFileStructure = (appPath: string): Promise<void> => {
return new Promise((resolve, reject) => {
CliUx.ux.info('Starting: ', `./${appPath}/.add-ons/bootstrap`);
Nihisil marked this conversation as resolved.
Show resolved Hide resolved
CliUx.ux.info('Starting: ', `${appPath}/.add-ons/bootstrap`);

try {
const destPath = `./${appPath}/src/assets/stylesheets/vendor/bootstrap/`;
fs.renameSync(`./${appPath}/.add-ons/bootstrap/`, destPath);
const destPath = `${appPath}/src/assets/stylesheets/vendor/bootstrap/`;
fs.renameSync(`${appPath}/.add-ons/bootstrap/`, destPath);

resolve();
} catch (error) {
Expand All @@ -42,7 +42,7 @@ const addBootstrapScssUseLine = (appPath: string): Promise<void> => {
CliUx.ux.info('Insert bootstrap scss import.');

try {
const indexScssPath = `./${appPath}/src/assets/stylesheets/application.scss`;
const indexScssPath = `${appPath}/src/assets/stylesheets/application.scss`;
const lineToAdd = `@use 'src/assets/stylesheets/vendor/bootstrap';`;

addLinesToFileAfterMatchedLine(
Expand All @@ -64,7 +64,7 @@ const addBootstrapScssUseLine = (appPath: string): Promise<void> => {
};

const installDevDependencies = (appPath: string): Promise<void> => {
return runCommand('npm', ['install', ...DEV_DEPENDENCIES], `./${appPath}/`);
return runCommand('npm', ['install', ...DEV_DEPENDENCIES], `${appPath}/`);
};

const setupBootstrap = async(appPath: string): Promise<void> => {
Expand Down
4 changes: 3 additions & 1 deletion packages/cli-tool/src/add-ons/ui-framework/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { CliUx } from '@oclif/core';

import { templateOptions } from '../../template/index';
import setupBootstrap from './bootstrap';
import setupTailwindCss from './tailwind-css';

Expand All @@ -14,13 +15,14 @@ export const UI_FRAMEWORK_OPTIONS = new Map<uiFrameworkKey, string>([
export const setUIFramework = async(
appPath: string,
uiFramework: uiFrameworkKey,
selectedTemplate: templateOptions,
): Promise<void> => {
switch (uiFramework) {
case 'bootstrap':
CliUx.ux.info('Configure Bootstrap...');
return setupBootstrap(appPath);
case 'tailwindCss':
CliUx.ux.info('Configure TailwindCSS...');
return setupTailwindCss(appPath);
return setupTailwindCss(appPath, selectedTemplate);
}
};
59 changes: 35 additions & 24 deletions packages/cli-tool/src/add-ons/ui-framework/tailwind-css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,20 @@ import { CliUx } from '@oclif/core';

import runCommand from '../../helpers/child-process';
import { replaceLine } from '../../helpers/file-editor';
import { templateOptions } from '../../template/index';

const DEV_DEPENDENCIES = [
'tailwindcss@^3.1.4',
'postcss@^8.4.14',
'postcss-import@^14.1.0',
'autoprefixer@^10.4.7',
];

const installDevDependencies = (appPath: string): Promise<void> => {
return runCommand(
'npm',
['install', '-D', ...DEV_DEPENDENCIES],
`./${appPath}/`,
`${appPath}/`,
);
};

Expand All @@ -24,8 +26,8 @@ const removeScssFileStructure = (appPath: string): Promise<void> => {
CliUx.ux.info('Remove SCSS files...');

try {
fs.rmSync(`./${appPath}/src/assets/stylesheets`, { recursive: true });
fs.rmSync(`./${appPath}/src/dummy.scss`);
fs.rmSync(`${appPath}/src/assets/stylesheets`, { recursive: true });
fs.rmSync(`${appPath}/src/dummy.scss`);

resolve();
} catch (error) {
Expand All @@ -45,19 +47,19 @@ const addTailwindFileStructure = (appPath: string): Promise<void> => {
CliUx.ux.info('Add TailwindCSS files...');

try {
const applicationCss = `./${appPath}/.add-ons/tailwind/stylesheets/application.css`;
const dummyCss = `./${appPath}/.add-ons/tailwind/stylesheets/dummy.css`;
const tailwindConfig = `./${appPath}/.add-ons/tailwind/tailwind.config.js`;
const postcssConfig = `./${appPath}/.add-ons/tailwind/postcss.config.js`;
const applicationCss = `${appPath}/.add-ons/tailwind/stylesheets/application.css`;
const dummyCss = `${appPath}/.add-ons/tailwind/stylesheets/dummy.css`;
const tailwindConfig = `${appPath}/.add-ons/tailwind/tailwind.config.js`;
const postcssConfig = `${appPath}/.add-ons/tailwind/postcss.config.js`;

fs.mkdirSync(`./${appPath}/src/assets/stylesheets/`);
fs.mkdirSync(`${appPath}/src/assets/stylesheets/`);
fs.renameSync(
applicationCss,
`./${appPath}/src/assets/stylesheets/application.css`,
`${appPath}/src/assets/stylesheets/application.css`,
);
fs.renameSync(dummyCss, `./${appPath}/src/dummy.css`);
fs.renameSync(tailwindConfig, `./${appPath}/tailwind.config.js`);
fs.renameSync(postcssConfig, `./${appPath}/postcss.config.js`);
fs.renameSync(dummyCss, `${appPath}/src/dummy.css`);
fs.renameSync(tailwindConfig, `${appPath}/tailwind.config.js`);
fs.renameSync(postcssConfig, `${appPath}/postcss.config.js`);

resolve();
} catch (error) {
Expand All @@ -68,20 +70,29 @@ const addTailwindFileStructure = (appPath: string): Promise<void> => {
});
};

const addTailwindCssImport = (appPath: string): Promise<void> => {
const addTailwindCssImport = (appPath: string, selectedTemplate: templateOptions): Promise<void> => {
return new Promise((resolve, reject) => {
CliUx.ux.info('Update css imports in App.tsx');

try {
const indexScssPath = `./${appPath}/src/App.tsx`;

replaceLine(
indexScssPath,
`import 'assets/stylesheets/application.scss';`,
`import 'assets/stylesheets/application.css';`,
);
replaceLine(indexScssPath, `import 'dummy.scss';`, `import 'dummy.css';`);

const indexScssPath = `${appPath}/src/App.tsx`;

if (selectedTemplate === 'webpack') {
replaceLine(
indexScssPath,
`import 'assets/stylesheets/application.scss';`,
`import 'assets/stylesheets/application.css';`,
);
replaceLine(indexScssPath, `import '@/dummy.scss';`, `import '@/dummy.css';`);
}
if (selectedTemplate === 'vite') {
replaceLine(
indexScssPath,
`import '@/assets/stylesheets/application.scss';`,
`import '@/assets/stylesheets/application.css';`,
);
replaceLine(indexScssPath, `import 'dummy.scss';`, `import 'dummy.css';`);
}
resolve();
} catch (error) {
CliUx.ux.info(
Expand All @@ -94,11 +105,11 @@ const addTailwindCssImport = (appPath: string): Promise<void> => {
});
};

const setupTailwindCss = async function(appPath: string): Promise<void> {
const setupTailwindCss = async function(appPath: string, selectedTemplate: templateOptions): Promise<void> {
return installDevDependencies(appPath)
.then((_value) => removeScssFileStructure(appPath))
.then((_value) => addTailwindFileStructure(appPath))
.then((_value) => addTailwindCssImport(appPath));
.then((_value) => addTailwindCssImport(appPath, selectedTemplate));
};

export default setupTailwindCss;
45 changes: 29 additions & 16 deletions packages/cli-tool/src/commands/generate/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import Inquirer from 'inquirer';
import { setUIFramework } from '../../add-ons/ui-framework/index';
import { setVersionControl } from '../../add-ons/version-control/index';
import { questions } from '../../helpers/questions';
import initializeCraApp from '../../template/initialize-cra-app';
import { initializeTemplate } from '../../template/index';

type generateArguments = { appName: string; templateReference: string; dest: string };

export default class Generate extends Command {
static description = 'Generate Nimble React application';
Expand All @@ -20,44 +22,55 @@ export default class Generate extends Command {
description: 'application name',
},
{
name: 'template',
name: 'dest',
required: false,
description:
'template location, use "file:{../path/to/your/local/template/repo}" for using a local cra template',
default: '@nimblehq',
'destination, defines in which folder the project folder will be created',
default: './',
},
{
name: 'dest',
name: 'templateReference',
required: false,
description:
'destination, defines in which folder the project folder will be created',
default: './',
description: 'Specify the branch to download the vite-template from or path to a local cra-template folder.',
default: '',
},
];

public async run(): Promise<void> {
public async parseArgs(): Promise<generateArguments> {
let destination = '';
const {
args: { appName, template, dest },
} = await this.parse(Generate);
args: { appName, templateReference, dest },
}: { args: generateArguments } = await this.parse(Generate);

const appPath = `${dest}${appName}`;
destination = dest.endsWith('/') ? dest : `${dest}/`;

return { appName, templateReference, dest: destination };
}

public async run(): Promise<void> {
const args = await this.parseArgs();
const answers = await Inquirer.prompt(questions);

const appPath = `${args.dest}${args.appName}`;

try {
this.log(
`Generating Nimble React app with the project name: ${appName}!`,
`Generating Nimble React app with the project name: ${args.appName}!`,
);

await initializeCraApp(appName, template, dest);
await initializeTemplate({
templateOption: answers.template,
...args,
});

setVersionControl(appPath, answers.versionControl);
await setUIFramework(appPath, answers.uiFramework);
await setUIFramework(appPath, answers.uiFramework, answers.template);

// Clean files after all steps
await this.cleanFiles(appPath);

// Display a final message
this.displayEndMessage(appName, appPath);
this.displayEndMessage(args.appName, appPath);
} catch (error) {
this.error(error as string | Error);
}
Expand Down
25 changes: 25 additions & 0 deletions packages/cli-tool/src/helpers/github.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import runCommand from './child-process';

type gitHubRepository = {
gitHubAccount: string;
repositoryName: string;
branch: string;
};

const downloadRepository = (
repository: gitHubRepository,
ouput: string,
dest: string,
): Promise<void> => {
return runCommand(
'curl',
[
`https://codeload.github.com/${repository.gitHubAccount}/${repository.repositoryName}/tar.gz/${repository.branch}`,
'--output',
`${ouput}.gz`,
],
dest,
);
};

export { downloadRepository, gitHubRepository };
8 changes: 8 additions & 0 deletions packages/cli-tool/src/helpers/questions.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
import { UI_FRAMEWORK_OPTIONS } from '../add-ons/ui-framework/index';
import { VERSION_CONTROL_OPTIONS } from '../add-ons/version-control/index';
import { TEMPLATE_OPTIONS } from '../template/index';
import getChoices from './choices';

const uiFrameworkChoices = getChoices(UI_FRAMEWORK_OPTIONS);
const versionControlChoices = getChoices(VERSION_CONTROL_OPTIONS);
const templateOptions = getChoices(TEMPLATE_OPTIONS);

export const questions = [
{
type: 'list',
name: 'template',
message: 'Select a template:',
choices: templateOptions,
},
{
type: 'list',
name: 'versionControl',
Expand Down
32 changes: 32 additions & 0 deletions packages/cli-tool/src/template/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import initializeCraApp from './initialize-cra-app';
import initializeViteApp from './initialize-vite-app';

export type templateOptions = 'webpack' | 'vite';
export const TEMPLATE_OPTIONS = new Map<templateOptions, string>([
['webpack', 'WebPack'],
['vite', 'Vite'],
]);

export const initializeTemplate = async({
appName,
templateOption,
templateReference,
dest,
}: {
appName: string;
templateOption: templateOptions;
templateReference: string;
dest: string;
}): Promise<void> => {
if (templateOption === 'vite') {
await initializeViteApp({
appName,
dest,
branch: templateReference,
});

return;
}

await initializeCraApp(appName, templateReference, dest);
};
6 changes: 6 additions & 0 deletions packages/cli-tool/src/template/initialize-cra-app.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import runCommand from '../helpers/child-process';

const DEFAULT_CRA_TEMPLATE = '@nimblehq';

const initializeCraApp = async(
appName: string,
template: string,
dest: string,
): Promise<void> => {
if (template === '') {
template = DEFAULT_CRA_TEMPLATE;
}

return runCommand('npx', [
'create-react-app',
`${appName}`,
Expand Down
Loading