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

Add an option to NextJS to set it up for github pages #292

Merged
merged 18 commits into from
Nov 3, 2022
134 changes: 124 additions & 10 deletions src/lib/project.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ const { red, green, reset } = require('chalk');

const shExec = util.promisify(sh.exec);

const isWindows = process.platform === 'win32';

/**
* Create a new zkApp project with recommended dir structure, Prettier config,
* testing lib, etc. Warns if already exists and does NOT overwrite.
Expand All @@ -19,8 +21,6 @@ const shExec = util.promisify(sh.exec);
* @return {Promise<void>}
*/
async function project({ name, ui }) {
const isWindows = process.platform === 'win32';

if (fs.existsSync(name)) {
console.error(red(`Directory already exists. Not proceeding`));
return;
Expand Down Expand Up @@ -70,7 +70,7 @@ async function project({ name, ui }) {
scaffoldSvelte();
break;
case 'next':
await scaffoldNext();
await scaffoldNext(name);
break;
case 'nuxt':
scaffoldNuxt();
Expand Down Expand Up @@ -280,8 +280,8 @@ function scaffoldSvelte() {
);
}

async function scaffoldNext() {
const prompt = new Select({
async function scaffoldNext(projectName) {
const tsPrompt = new Select({
message: (state) =>
message(state, 'Do you want your NextJS project to use TypeScript?'),
choices: ['yes', 'no'],
Expand All @@ -290,14 +290,29 @@ async function scaffoldNext() {

let useTypescript;
try {
useTypescript = await prompt.run();
useTypescript = (await tsPrompt.run()) == 'yes';
} catch (err) {
// If ctrl+c is pressed it will throw.
return;
}

const ghPagesPrompt = new Select({
message: (state) =>
message(state, 'Do you want to setup your project for github pages?'),
choices: ['no', 'yes'],
prefix: (state) => prefix(state),
});

let useGHPages;
try {
useGHPages = (await ghPagesPrompt.run()) == 'yes';
} catch (err) {
// If ctrl+c is pressed it will throw.
return;
}

let args = ['create-next-app@latest', 'ui', '--use-npm'];
if (useTypescript === 'yes') args.push('--ts');
if (useTypescript) args.push('--ts');

// https://nextjs.org/docs/api-reference/create-next-app#options
spawnSync('npx', args, {
Expand All @@ -311,10 +326,14 @@ async function scaffoldNext() {
let newNextConfig = nextConfig.replace(
/^}(.*?)$/gm, // Search for the last '}' in the file.
`
pageExtensions: ['page.tsx', 'page.ts', 'page.jsx', 'page.js'],
webpack(config) {
config.resolve.alias = {
...config.resolve.alias,
snarkyjs: require('path').resolve('./node_modules/snarkyjs'),
snarkyjs: require('path').resolve('${path.join(
'node_modules',
'snarkyjs'
)}'),
}
return config;
},
Expand Down Expand Up @@ -345,6 +364,15 @@ async function scaffoldNext() {
);
fs.writeFileSync(path.join('ui', 'next.config.js'), newNextConfig);

sh.mv(
path.join('ui', 'pages', '_app.tsx'),
path.join('ui', 'pages', '_app.page.tsx')
);
sh.mv(
path.join('ui', 'pages', 'index.tsx'),
path.join('ui', 'pages', 'index.page.tsx')
);

const tsconfig = `
{
"compilerOptions": {
Expand Down Expand Up @@ -372,13 +400,99 @@ async function scaffoldNext() {
}
`;

if (useTypescript == 'yes') {
if (useTypescript) {
fs.writeFileSync(path.join('ui', 'tsconfig.json'), tsconfig);

// Add a script to the package.json
let x = fs.readJSONSync(`ui/package.json`);
let x = fs.readJSONSync(path.join('ui', 'package.json'));
x.scripts['ts-watch'] = 'tsc --noEmit --incremental --watch';
fs.writeJSONSync(path.join('ui', 'package.json'), x, { spaces: 2 });
}

if (useGHPages) {
const nextConfig = fs.readFileSync(
path.join('ui', 'next.config.js'),
'utf8'
);
console.log(
'Using project name ' +
projectName +
' for github repo name. Please change in next.config.js and pages/reactCOIServiceWorker.tsx if this is not correct or changes'
);

let newNextConfig = nextConfig.replace(
' }\n};',
` },
images: {
unoptimized: true,
},
basePath: process.env.NODE_ENV === 'production' ? '/${projectName}' : undefined, // update if your repo name changes for 'npm run deploy' to work successfully
assetPrefix: process.env.NODE_ENV === 'production' ? '/${projectName}/' : undefined, // update if your repo name changes for 'npm run deploy' to work successfully
};`
);
newNextConfig = newNextConfig.replace(
'return config;',
`config.optimization.minimizer = [];
return config;`
);
fs.writeFileSync(path.join('ui', 'next.config.js'), newNextConfig);

// Add some scripts to the package.json
let x = fs.readJSONSync(`ui/package.json`);
x.scripts['export'] = 'next export';
const deployScript = `next build && next export && ${
isWindows
? `type nul > ${path.join('out', '.nojekyll')}`
: `touch ${path.join('out', '.nojekyll')}`
} && git add -f out && git commit -m "Deploy gh-pages" && cd .. && git subtree push --prefix ui/out origin gh-pages`;
x.scripts['deploy'] = deployScript;
fs.writeJSONSync(`ui/package.json`, x, { spaces: 2 });

sh.cd('ui');
await step(
'COI-ServiceWorker: NPM install',
`npm install coi-serviceworker --save > ${
isWindows ? 'NUL' : '"/dev/null" 2>&1'
}`
);
sh.cp(
path.join(
'node_modules',
'coi-serviceworker',
'coi-serviceworker.min.js'
),
'./public/'
);
sh.cd('..');

let apptsx = fs.readFileSync(
path.join('ui', 'pages', '_app.page.tsx'),
'utf8'
);
apptsx = apptsx.replace(
'export default function',
`import './reactCOIServiceWorker';

export default function`
);
fs.writeFileSync(path.join('ui', 'pages', '_app.page.tsx'), apptsx);

fs.writeFileSync(
path.join('ui', 'pages', 'reactCOIServiceWorker.tsx'),
`
export {}

function loadCOIServiceWorker() {
if (typeof window !== 'undefined' && window.location.hostname != 'localhost') {
const coi = window.document.createElement('script');
coi.setAttribute('src','/${projectName}/coi-serviceworker.min.js'); // update if your repo name changes for npm run deploy to work successfully
window.document.head.appendChild(coi);
}
}

loadCOIServiceWorker();
`
);
}
}

Expand Down