fix(nextjs): fix Next.js schematics to support dynamic routes and remove unnecessary next plugins (as of 9.5) (#3574)
Closes #2478, #2490
This commit is contained in:
parent
26c13d66a7
commit
9f35646c65
@ -38,6 +38,14 @@ nx g component my-component --project=mylib --classComponent
|
|||||||
|
|
||||||
## Options
|
## Options
|
||||||
|
|
||||||
|
### directory
|
||||||
|
|
||||||
|
Alias(es): d
|
||||||
|
|
||||||
|
Type: `string`
|
||||||
|
|
||||||
|
Create the page under this directory (can be nested). Will be created under 'pages/'.
|
||||||
|
|
||||||
### export
|
### export
|
||||||
|
|
||||||
Alias(es): e
|
Alias(es): e
|
||||||
|
|||||||
@ -38,6 +38,14 @@ nx g component my-component --project=mylib --classComponent
|
|||||||
|
|
||||||
## Options
|
## Options
|
||||||
|
|
||||||
|
### directory
|
||||||
|
|
||||||
|
Alias(es): d
|
||||||
|
|
||||||
|
Type: `string`
|
||||||
|
|
||||||
|
Create the page under this directory (can be nested). Will be created under 'pages/'.
|
||||||
|
|
||||||
### export
|
### export
|
||||||
|
|
||||||
Alias(es): e
|
Alias(es): e
|
||||||
|
|||||||
@ -80,31 +80,18 @@ forEachCli('nx', () => {
|
|||||||
|
|
||||||
runCLI(`generate @nrwl/next:app ${appName} --no-interactive`);
|
runCLI(`generate @nrwl/next:app ${appName} --no-interactive`);
|
||||||
|
|
||||||
runCLI(`generate @nrwl/react:lib ${libName} --no-interactive`);
|
runCLI(
|
||||||
|
`generate @nrwl/react:lib ${libName} --no-interactive --style=none`
|
||||||
|
);
|
||||||
|
|
||||||
const mainPath = `apps/${appName}/pages/index.tsx`;
|
const mainPath = `apps/${appName}/pages/index.tsx`;
|
||||||
updateFile(mainPath, `import '@proj/${libName}';\n` + readFile(mainPath));
|
updateFile(mainPath, `import '@proj/${libName}';\n` + readFile(mainPath));
|
||||||
updateFile(
|
|
||||||
`apps/${appName}/next.config.js`,
|
|
||||||
`
|
|
||||||
const withCSS = require('@zeit/next-css');
|
|
||||||
module.exports = withCSS({
|
|
||||||
cssModules: false,
|
|
||||||
generateBuildId: function () {
|
|
||||||
return 'fixed';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
`
|
|
||||||
);
|
|
||||||
|
|
||||||
await checkApp(appName, {
|
await checkApp(appName, {
|
||||||
checkUnitTest: true,
|
checkUnitTest: true,
|
||||||
checkLint: true,
|
checkLint: true,
|
||||||
checkE2E: false,
|
checkE2E: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
// check that the configuration was consumed
|
|
||||||
expect(readFile(`dist/apps/${appName}/.next/BUILD_ID`)).toEqual('fixed');
|
|
||||||
}, 120000);
|
}, 120000);
|
||||||
|
|
||||||
it('should be able to dynamically load a lib', async () => {
|
it('should be able to dynamically load a lib', async () => {
|
||||||
@ -113,7 +100,9 @@ module.exports = withCSS({
|
|||||||
const libName = uniq('lib');
|
const libName = uniq('lib');
|
||||||
|
|
||||||
runCLI(`generate @nrwl/next:app ${appName} --no-interactive`);
|
runCLI(`generate @nrwl/next:app ${appName} --no-interactive`);
|
||||||
runCLI(`generate @nrwl/react:lib ${libName} --no-interactive`);
|
runCLI(
|
||||||
|
`generate @nrwl/react:lib ${libName} --no-interactive --style=none`
|
||||||
|
);
|
||||||
|
|
||||||
const mainPath = `apps/${appName}/pages/index.tsx`;
|
const mainPath = `apps/${appName}/pages/index.tsx`;
|
||||||
updateFile(
|
updateFile(
|
||||||
@ -181,8 +170,8 @@ module.exports = withCSS({
|
|||||||
import { TestComponent } from '@proj/${tsxLibName}';\n\n
|
import { TestComponent } from '@proj/${tsxLibName}';\n\n
|
||||||
` +
|
` +
|
||||||
content.replace(
|
content.replace(
|
||||||
`<main>`,
|
`</h2>`,
|
||||||
`<main>
|
`</h2>
|
||||||
<div>
|
<div>
|
||||||
{testFn()}
|
{testFn()}
|
||||||
<TestComponent text="Hello Next.JS" />
|
<TestComponent text="Hello Next.JS" />
|
||||||
|
|||||||
@ -166,7 +166,7 @@
|
|||||||
"mime": "2.4.4",
|
"mime": "2.4.4",
|
||||||
"mini-css-extract-plugin": "0.8.0",
|
"mini-css-extract-plugin": "0.8.0",
|
||||||
"minimatch": "3.0.4",
|
"minimatch": "3.0.4",
|
||||||
"next": "9.3.3",
|
"next": "9.5.2",
|
||||||
"ng-packagr": "9.1.0",
|
"ng-packagr": "9.1.0",
|
||||||
"ngrx-store-freeze": "0.2.4",
|
"ngrx-store-freeze": "0.2.4",
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
|
|||||||
@ -39,7 +39,7 @@
|
|||||||
"version": "10.1.0-beta.0",
|
"version": "10.1.0-beta.0",
|
||||||
"packages": {
|
"packages": {
|
||||||
"next": {
|
"next": {
|
||||||
"version": "9.5.1",
|
"version": "9.5.2",
|
||||||
"alwaysAddToPackageJson": false
|
"alwaysAddToPackageJson": false
|
||||||
},
|
},
|
||||||
"node-sass": {
|
"node-sass": {
|
||||||
|
|||||||
@ -40,6 +40,7 @@ function run(
|
|||||||
exportApp(
|
exportApp(
|
||||||
root,
|
root,
|
||||||
{
|
{
|
||||||
|
statusMessage: 'Exporting',
|
||||||
silent: options.silent,
|
silent: options.silent,
|
||||||
threads: options.threads,
|
threads: options.threads,
|
||||||
outdir: `${buildOptions.outputPath}/exported`,
|
outdir: `${buildOptions.outputPath}/exported`,
|
||||||
|
|||||||
@ -56,7 +56,9 @@ describe('app', () => {
|
|||||||
{ name: 'myApp', style: 'scss' },
|
{ name: 'myApp', style: 'scss' },
|
||||||
appTree
|
appTree
|
||||||
);
|
);
|
||||||
expect(result.exists('apps/my-app/pages/index.scss')).toEqual(true);
|
expect(result.exists('apps/my-app/pages/index.module.scss')).toEqual(
|
||||||
|
true
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -1,11 +1,4 @@
|
|||||||
<% if (style === 'scss') { %>
|
<% if (style === 'less') { %>
|
||||||
const withSass = require('@zeit/next-sass');
|
|
||||||
module.exports = withSass({
|
|
||||||
// Set this to true if you use CSS modules.
|
|
||||||
// See: https://github.com/css-modules/css-modules
|
|
||||||
cssModules: false
|
|
||||||
});
|
|
||||||
<% } else if (style === 'less') { %>
|
|
||||||
const withLess = require('@zeit/next-less');
|
const withLess = require('@zeit/next-less');
|
||||||
module.exports = withLess({
|
module.exports = withLess({
|
||||||
// Set this to true if you use CSS modules.
|
// Set this to true if you use CSS modules.
|
||||||
@ -19,13 +12,6 @@ module.exports = withStylus({
|
|||||||
// See: https://github.com/css-modules/css-modules
|
// See: https://github.com/css-modules/css-modules
|
||||||
cssModules: false
|
cssModules: false
|
||||||
});
|
});
|
||||||
<% } else if (style === 'css') { %>
|
|
||||||
const withCSS = require('@zeit/next-css');
|
|
||||||
module.exports = withCSS({
|
|
||||||
// Set this to true if you use CSS modules.
|
|
||||||
// See: https://github.com/css-modules/css-modules
|
|
||||||
cssModules: false
|
|
||||||
});
|
|
||||||
<% } else if (
|
<% } else if (
|
||||||
style === 'styled-components'
|
style === 'styled-components'
|
||||||
||style === '@emotion/styled'
|
||style === '@emotion/styled'
|
||||||
@ -34,11 +20,6 @@ module.exports = withCSS({
|
|||||||
) { %>
|
) { %>
|
||||||
module.exports ={};
|
module.exports ={};
|
||||||
<% } else {
|
<% } else {
|
||||||
// Defaults to CSS %>
|
// Defaults to CSS/SASS (which don't need plugin as of Next 9.3) %>
|
||||||
const withCSS = require('@zeit/next-css');
|
module.exports ={};
|
||||||
module.exports = withCSS({
|
|
||||||
// Set this to true if you use CSS modules.
|
|
||||||
// See: https://github.com/css-modules/css-modules
|
|
||||||
cssModules: false
|
|
||||||
});
|
|
||||||
<% } %>
|
<% } %>
|
||||||
|
|||||||
@ -0,0 +1,2 @@
|
|||||||
|
.page {
|
||||||
|
}
|
||||||
@ -1,16 +1,15 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
<% if (styledModule && styledModule !== 'styled-jsx') {
|
<% if (styledModule && styledModule !== 'styled-jsx') {
|
||||||
var wrapper = 'StyledApp';
|
var wrapper = 'StyledPage';
|
||||||
%>import styled from '<%= styledModule %>';<% } else {
|
%>import styled from '<%= styledModule %>';<% } else {
|
||||||
var wrapper = 'div';
|
var wrapper = 'div';
|
||||||
%>
|
%>
|
||||||
<%= style !== 'styled-jsx' ? `import './${fileName}.${style}';` : '' %>
|
<%= style !== 'styled-jsx' ? `import styles from './${fileName}.module.${style}';` : '' %>
|
||||||
<% }
|
<% }
|
||||||
%>
|
%>
|
||||||
import { ReactComponent as NxLogo } from '../public/nx-logo-white.svg';
|
|
||||||
|
|
||||||
<% if (styledModule && styledModule !== 'styled-jsx') { %>
|
<% if (styledModule && styledModule !== 'styled-jsx') { %>
|
||||||
const StyledApp = styled.div`<%= styleContent %>`;
|
const StyledPage = styled.div`<%= styleContent %>`;
|
||||||
<% }%>
|
<% }%>
|
||||||
|
|
||||||
export const Index = () => {
|
export const Index = () => {
|
||||||
@ -20,7 +19,7 @@ export const Index = () => {
|
|||||||
* Note: The corresponding styles are in the ./${fileName}.${style} file.
|
* Note: The corresponding styles are in the ./${fileName}.${style} file.
|
||||||
*/
|
*/
|
||||||
return (
|
return (
|
||||||
<<%= wrapper %><% if (!styledModule || styledModule === 'styled-jsx') {%> className="app"<% } %>>
|
<<%= wrapper %><% if (!styledModule || styledModule === 'styled-jsx') {%> className={styles.page}<% } %>>
|
||||||
<%= styledModule === 'styled-jsx' ? `<style jsx>{\`${styleContent}\`}</style>` : `` %>
|
<%= styledModule === 'styled-jsx' ? `<style jsx>{\`${styleContent}\`}</style>` : `` %>
|
||||||
<%= appContent %>
|
<%= appContent %>
|
||||||
</<%= wrapper %>>
|
</<%= wrapper %>>
|
||||||
|
|||||||
@ -0,0 +1,26 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { AppProps } from 'next/app';
|
||||||
|
import Head from 'next/head';
|
||||||
|
import { ReactComponent as NxLogo } from '../public/nx-logo-white.svg';
|
||||||
|
import './styles.css';
|
||||||
|
|
||||||
|
const CustomApp = ({ Component, pageProps }: AppProps) => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Head>
|
||||||
|
<title>Welcome to <%= name %>!</title>
|
||||||
|
</Head>
|
||||||
|
<div className="app">
|
||||||
|
<header className="flex">
|
||||||
|
<NxLogo width="75" height="50" />
|
||||||
|
<h1>Welcome to <%= name %>!</h1>
|
||||||
|
</header>
|
||||||
|
<main>
|
||||||
|
<Component {...pageProps}/>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CustomApp;
|
||||||
@ -19,7 +19,6 @@ export default class CustomDocument extends Document<{ styleTags: ReactElement[]
|
|||||||
return (
|
return (
|
||||||
<html>
|
<html>
|
||||||
<Head>
|
<Head>
|
||||||
<title>Welcome to <%= name %>!</title>
|
|
||||||
{this.props.styleTags}
|
{this.props.styleTags}
|
||||||
</Head>
|
</Head>
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
@ -8,9 +8,4 @@ describe('Index', () => {
|
|||||||
const { baseElement } = render(<Index />);
|
const { baseElement } = render(<Index />);
|
||||||
expect(baseElement).toBeTruthy();
|
expect(baseElement).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have a greeting as the title', () => {
|
|
||||||
const { getByText } = render(<Index />);
|
|
||||||
expect(getByText('Welcome to <%= projectName %>!')).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,10 +1,5 @@
|
|||||||
export function createAppJsx(name: string) {
|
export function createAppJsx(name: string) {
|
||||||
return `
|
return `
|
||||||
<header className="flex">
|
|
||||||
<NxLogo alt="" width="75" height="50" />
|
|
||||||
<h1>Welcome to ${name}!</h1>
|
|
||||||
</header>
|
|
||||||
<main>
|
|
||||||
<h2>Resources & Tools</h2>
|
<h2>Resources & Tools</h2>
|
||||||
<p>
|
<p>
|
||||||
Thank you for using and showing some ♥ for Nx.
|
Thank you for using and showing some ♥ for Nx.
|
||||||
@ -86,80 +81,60 @@ nx affected:test
|
|||||||
nx affected:e2e
|
nx affected:e2e
|
||||||
\`}</pre>
|
\`}</pre>
|
||||||
</details>
|
</details>
|
||||||
</main>
|
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface CreateStyleRulesOptions {
|
export function createStyleRules() {
|
||||||
isUsingJsxBasedSolution: boolean;
|
return `
|
||||||
createHostBlock: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createStyleRules({
|
|
||||||
isUsingJsxBasedSolution,
|
|
||||||
createHostBlock,
|
|
||||||
}: CreateStyleRulesOptions) {
|
|
||||||
const childSelectorPrefix = isUsingJsxBasedSolution ? '' : '.app';
|
|
||||||
return `${
|
|
||||||
createHostBlock
|
|
||||||
? `
|
|
||||||
.app {
|
.app {
|
||||||
font-family: sans-serif;
|
font-family: sans-serif;
|
||||||
min-width: 300px;
|
min-width: 300px;
|
||||||
max-width: 600px;
|
max-width: 600px;
|
||||||
margin: 50px auto;
|
margin: 50px auto;
|
||||||
}
|
}
|
||||||
`
|
|
||||||
: `
|
|
||||||
font-family: sans-serif;
|
|
||||||
min-width: 300px;
|
|
||||||
max-width: 600px;
|
|
||||||
margin: 50px auto;
|
|
||||||
`
|
|
||||||
}
|
|
||||||
|
|
||||||
${childSelectorPrefix} .gutter-left {
|
.app .gutter-left {
|
||||||
margin-left: 9px;
|
margin-left: 9px;
|
||||||
}
|
}
|
||||||
|
|
||||||
${childSelectorPrefix} .col-span-2 {
|
.app .col-span-2 {
|
||||||
grid-column: span 2;
|
grid-column: span 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
${childSelectorPrefix} .flex {
|
.app .flex {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
${childSelectorPrefix} header {
|
.app header {
|
||||||
background-color: #143055;
|
background-color: #143055;
|
||||||
color: white;
|
color: white;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
${childSelectorPrefix} main {
|
.app main {
|
||||||
padding: 0 36px;
|
padding: 0 36px;
|
||||||
}
|
}
|
||||||
|
|
||||||
${childSelectorPrefix} p {
|
.app p {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
${childSelectorPrefix} h1 {
|
.app h1 {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin-left: 18px;
|
margin-left: 18px;
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
${childSelectorPrefix} h2 {
|
.app h2 {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
margin: 40px 0 10px 0;
|
margin: 40px 0 10px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
${childSelectorPrefix} .resources {
|
.app .resources {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
list-style: none;
|
list-style: none;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
@ -168,7 +143,7 @@ ${childSelectorPrefix} .resources {
|
|||||||
grid-template-columns: 1fr 1fr;
|
grid-template-columns: 1fr 1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
${childSelectorPrefix} .resource {
|
.app .resource {
|
||||||
color: #0094ba;
|
color: #0094ba;
|
||||||
height: 36px;
|
height: 36px;
|
||||||
background-color: rgba(0, 0, 0, 0);
|
background-color: rgba(0, 0, 0, 0);
|
||||||
@ -178,18 +153,18 @@ ${childSelectorPrefix} .resource {
|
|||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
${childSelectorPrefix} .resource:hover {
|
.app .resource:hover {
|
||||||
background-color: rgba(68, 138, 255, 0.04);
|
background-color: rgba(68, 138, 255, 0.04);
|
||||||
}
|
}
|
||||||
|
|
||||||
${childSelectorPrefix} pre {
|
.app pre {
|
||||||
padding: 9px;
|
padding: 9px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
background-color: black;
|
background-color: black;
|
||||||
color: #eee;
|
color: #eee;
|
||||||
}
|
}
|
||||||
|
|
||||||
${childSelectorPrefix} details {
|
.app details {
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
color: #333;
|
color: #333;
|
||||||
background-color: rgba(0, 0, 0, 0);
|
background-color: rgba(0, 0, 0, 0);
|
||||||
@ -198,25 +173,25 @@ ${childSelectorPrefix} details {
|
|||||||
margin-bottom: 9px;
|
margin-bottom: 9px;
|
||||||
}
|
}
|
||||||
|
|
||||||
${childSelectorPrefix} summary {
|
.app summary {
|
||||||
outline: none;
|
outline: none;
|
||||||
height: 36px;
|
height: 36px;
|
||||||
line-height: 36px;
|
line-height: 36px;
|
||||||
}
|
}
|
||||||
|
|
||||||
${childSelectorPrefix} .github-star-container {
|
.app .github-star-container {
|
||||||
margin-top: 12px;
|
margin-top: 12px;
|
||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
${childSelectorPrefix} .github-star-container a {
|
.app .github-star-container a {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
color: #333;
|
color: #333;
|
||||||
}
|
}
|
||||||
|
|
||||||
${childSelectorPrefix} .github-star-badge {
|
.app .github-star-badge {
|
||||||
color: #24292e;
|
color: #24292e;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -229,12 +204,12 @@ ${childSelectorPrefix} .github-star-badge {
|
|||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
${childSelectorPrefix} .github-star-badge:hover {
|
.app .github-star-badge:hover {
|
||||||
background-image: linear-gradient(-180deg,#f0f3f6,#e6ebf1 90%);
|
background-image: linear-gradient(-180deg,#f0f3f6,#e6ebf1 90%);
|
||||||
border-color: rgba(27,31,35,.35);
|
border-color: rgba(27,31,35,.35);
|
||||||
background-position: -.5em;
|
background-position: -.5em;
|
||||||
}
|
}
|
||||||
${childSelectorPrefix} .github-star-badge .material-icons {
|
.app .github-star-badge .material-icons {
|
||||||
height: 16px;
|
height: 16px;
|
||||||
width: 16px;
|
width: 16px;
|
||||||
margin-right: 4px;
|
margin-right: 4px;
|
||||||
|
|||||||
@ -24,11 +24,7 @@ export function createApplicationFiles(options: NormalizedSchema): Rule {
|
|||||||
tmpl: '',
|
tmpl: '',
|
||||||
offsetFromRoot: offsetFromRoot(options.appProjectRoot),
|
offsetFromRoot: offsetFromRoot(options.appProjectRoot),
|
||||||
appContent: createAppJsx(options.name),
|
appContent: createAppJsx(options.name),
|
||||||
styleContent: createStyleRules({
|
styleContent: createStyleRules(),
|
||||||
isUsingJsxBasedSolution: !!options.styledModule,
|
|
||||||
createHostBlock:
|
|
||||||
!options.styledModule || options.styledModule === 'styled-jsx',
|
|
||||||
}),
|
|
||||||
}),
|
}),
|
||||||
options.styledModule
|
options.styledModule
|
||||||
? filter((file) => !file.endsWith(`.${options.style}`))
|
? filter((file) => !file.endsWith(`.${options.style}`))
|
||||||
|
|||||||
@ -32,6 +32,11 @@
|
|||||||
},
|
},
|
||||||
"x-prompt": "What name would you like to use for the component?"
|
"x-prompt": "What name would you like to use for the component?"
|
||||||
},
|
},
|
||||||
|
"directory": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Create the component under this directory (can be nested).",
|
||||||
|
"alias": "d"
|
||||||
|
},
|
||||||
"style": {
|
"style": {
|
||||||
"description": "The file extension to be used for style files.",
|
"description": "The file extension to be used for style files.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
|||||||
@ -23,4 +23,24 @@ describe('component', () => {
|
|||||||
expect(tree.exists('apps/my-app/src/pages/hello.tsx')).toBeTruthy();
|
expect(tree.exists('apps/my-app/src/pages/hello.tsx')).toBeTruthy();
|
||||||
expect(tree.exists('apps/my-app/src/pages/hello.css')).toBeTruthy();
|
expect(tree.exists('apps/my-app/src/pages/hello.css')).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should support dynamic routes and directories', async () => {
|
||||||
|
const tree = await runSchematic(
|
||||||
|
'page',
|
||||||
|
{ name: '[dynamic]', directory: 'posts', project: projectName },
|
||||||
|
appTree
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
tree.exists('apps/my-app/src/pages/posts/[dynamic].tsx')
|
||||||
|
).toBeTruthy();
|
||||||
|
expect(
|
||||||
|
tree.exists('apps/my-app/src/pages/posts/[dynamic].css')
|
||||||
|
).toBeTruthy();
|
||||||
|
|
||||||
|
const content = tree
|
||||||
|
.read('apps/my-app/src/pages/posts/[dynamic].tsx')
|
||||||
|
.toString();
|
||||||
|
expect(content).toMatch(/DynamicProps/);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,12 +1,6 @@
|
|||||||
import { chain, externalSchematic, Rule } from '@angular-devkit/schematics';
|
import { chain, externalSchematic, Rule } from '@angular-devkit/schematics';
|
||||||
import { addStyleDependencies } from '../../utils/styles';
|
import { addStyleDependencies } from '../../utils/styles';
|
||||||
|
import { Schema } from './schema';
|
||||||
interface Schema {
|
|
||||||
name: string;
|
|
||||||
project: string;
|
|
||||||
style: string;
|
|
||||||
withTests?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This schematic is basically the React component one, but for Next we need
|
* This schematic is basically the React component one, but for Next we need
|
||||||
@ -17,7 +11,7 @@ export default function (options: Schema): Rule {
|
|||||||
return chain([
|
return chain([
|
||||||
externalSchematic('@nrwl/react', 'component', {
|
externalSchematic('@nrwl/react', 'component', {
|
||||||
...options,
|
...options,
|
||||||
directory: 'pages', // This HAS to be here or Next won't work!
|
directory: options.directory ? `pages/${options.directory}` : 'pages',
|
||||||
pascalCaseFiles: false,
|
pascalCaseFiles: false,
|
||||||
export: false,
|
export: false,
|
||||||
classComponent: false,
|
classComponent: false,
|
||||||
|
|||||||
9
packages/next/src/schematics/page/schema.d.ts
vendored
Normal file
9
packages/next/src/schematics/page/schema.d.ts
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
export interface Schema {
|
||||||
|
name: string;
|
||||||
|
directory: string;
|
||||||
|
fileName: string;
|
||||||
|
project: string;
|
||||||
|
style: string;
|
||||||
|
withTests?: boolean;
|
||||||
|
js?: boolean;
|
||||||
|
}
|
||||||
@ -32,6 +32,11 @@
|
|||||||
},
|
},
|
||||||
"x-prompt": "What name would you like to use for the component?"
|
"x-prompt": "What name would you like to use for the component?"
|
||||||
},
|
},
|
||||||
|
"directory": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Create the page under this directory (can be nested). Will be created under 'pages/'.",
|
||||||
|
"alias": "d"
|
||||||
|
},
|
||||||
"style": {
|
"style": {
|
||||||
"description": "The file extension to be used for style files.",
|
"description": "The file extension to be used for style files.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
|||||||
@ -4,11 +4,9 @@ import { CSS_IN_JS_DEPENDENCIES } from '@nrwl/react';
|
|||||||
import {
|
import {
|
||||||
babelPluginStyledComponentsVersion,
|
babelPluginStyledComponentsVersion,
|
||||||
emotionServerVersion,
|
emotionServerVersion,
|
||||||
zeitNextCss,
|
|
||||||
zeitNextLess,
|
|
||||||
zeitNextSass,
|
|
||||||
zeitNextStylus,
|
|
||||||
nodeSass,
|
nodeSass,
|
||||||
|
zeitNextLess,
|
||||||
|
zeitNextStylus,
|
||||||
} from './versions';
|
} from './versions';
|
||||||
|
|
||||||
export const NEXT_SPECIFIC_STYLE_DEPENDENCIES = {
|
export const NEXT_SPECIFIC_STYLE_DEPENDENCIES = {
|
||||||
@ -27,15 +25,11 @@ export const NEXT_SPECIFIC_STYLE_DEPENDENCIES = {
|
|||||||
devDependencies: CSS_IN_JS_DEPENDENCIES['@emotion/styled'].devDependencies,
|
devDependencies: CSS_IN_JS_DEPENDENCIES['@emotion/styled'].devDependencies,
|
||||||
},
|
},
|
||||||
css: {
|
css: {
|
||||||
dependencies: {
|
dependencies: {},
|
||||||
'@zeit/next-css': zeitNextCss,
|
|
||||||
},
|
|
||||||
devDependencies: {},
|
devDependencies: {},
|
||||||
},
|
},
|
||||||
scss: {
|
scss: {
|
||||||
dependencies: {
|
dependencies: {},
|
||||||
'@zeit/next-sass': zeitNextSass,
|
|
||||||
},
|
|
||||||
devDependencies: {
|
devDependencies: {
|
||||||
'node-sass': nodeSass,
|
'node-sass': nodeSass,
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
export const nxVersion = '*';
|
export const nxVersion = '*';
|
||||||
|
|
||||||
export const nextVersion = '9.5.1';
|
export const nextVersion = '9.5.2';
|
||||||
export const zeitNextCss = '1.0.1';
|
export const zeitNextCss = '1.0.1';
|
||||||
export const zeitNextSass = '1.0.1';
|
export const zeitNextSass = '1.0.1';
|
||||||
export const nodeSass = '4.14.1';
|
export const nodeSass = '4.14.1';
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { schema } from '@angular-devkit/core';
|
import { schema } from '@angular-devkit/core';
|
||||||
import { fileSync } from 'tmp';
|
import { fileSync } from 'tmp';
|
||||||
import { readFileSync, writeFileSync, unlinkSync } from 'fs';
|
import { readFileSync, unlinkSync, writeFileSync } from 'fs';
|
||||||
import { TestingArchitectHost } from '@angular-devkit/architect/testing';
|
import { TestingArchitectHost } from '@angular-devkit/architect/testing';
|
||||||
import { Architect } from '@angular-devkit/architect';
|
import { Architect } from '@angular-devkit/architect';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
@ -89,7 +89,6 @@ describe('Command Runner Builder', () => {
|
|||||||
//wait a tick for the serial runner to schedule the first task
|
//wait a tick for the serial runner to schedule the first task
|
||||||
await Promise.resolve();
|
await Promise.resolve();
|
||||||
const run = await scheduleRun;
|
const run = await scheduleRun;
|
||||||
const result = await run.result;
|
|
||||||
|
|
||||||
expect(exec).toHaveBeenCalledWith(`echo --a=123 --b=456`, {
|
expect(exec).toHaveBeenCalledWith(`echo --a=123 --b=456`, {
|
||||||
stdio: [0, 1, 2],
|
stdio: [0, 1, 2],
|
||||||
|
|||||||
27
packages/workspace/src/utils/name-utils.spec.ts
Normal file
27
packages/workspace/src/utils/name-utils.spec.ts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import * as utils from './name-utils';
|
||||||
|
|
||||||
|
describe('name-utils', () => {
|
||||||
|
it('should support class names', () => {
|
||||||
|
expect(utils.toClassName('foo-bar')).toEqual('FooBar');
|
||||||
|
expect(utils.toClassName('foo_bar')).toEqual('FooBar');
|
||||||
|
expect(utils.toClassName('fooBar')).toEqual('FooBar');
|
||||||
|
expect(utils.toClassName('[fooBar]')).toEqual('FooBar');
|
||||||
|
expect(utils.toClassName('[...fooBar]')).toEqual('FooBar');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should support property names', () => {
|
||||||
|
expect(utils.toPropertyName('foo-bar')).toEqual('fooBar');
|
||||||
|
expect(utils.toPropertyName('foo_bar')).toEqual('fooBar');
|
||||||
|
expect(utils.toPropertyName('FooBar')).toEqual('fooBar');
|
||||||
|
expect(utils.toPropertyName('[fooBar]')).toEqual('fooBar');
|
||||||
|
expect(utils.toPropertyName('[...fooBar]')).toEqual('fooBar');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should support file names', () => {
|
||||||
|
expect(utils.toFileName('foo-bar')).toEqual('foo-bar');
|
||||||
|
expect(utils.toFileName('foo_bar')).toEqual('foo-bar');
|
||||||
|
expect(utils.toFileName('FooBar')).toEqual('foo-bar');
|
||||||
|
expect(utils.toFileName('[fooBar]')).toEqual('[foo-bar]');
|
||||||
|
expect(utils.toFileName('[...fooBar]')).toEqual('[...foo-bar]');
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -34,6 +34,7 @@ export function toPropertyName(s: string): string {
|
|||||||
.replace(/(-|_|\.|\s)+(.)?/g, (_, __, chr) =>
|
.replace(/(-|_|\.|\s)+(.)?/g, (_, __, chr) =>
|
||||||
chr ? chr.toUpperCase() : ''
|
chr ? chr.toUpperCase() : ''
|
||||||
)
|
)
|
||||||
|
.replace(/[^a-zA-Z\d]/g, '')
|
||||||
.replace(/^([A-Z])/, (m) => m.toLowerCase());
|
.replace(/^([A-Z])/, (m) => m.toLowerCase());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user