mirror of
https://github.com/phuoc-ng/csslayout.git
synced 2025-08-07 06:37:01 +02:00
Add layout
This commit is contained in:
14
.babelrc
14
.babelrc
@@ -1,14 +0,0 @@
|
|||||||
{
|
|
||||||
"plugins": [
|
|
||||||
"@loadable/babel-plugin",
|
|
||||||
["prismjs", {
|
|
||||||
"languages": ["css", "html", "javascript", "jsx", "tsx"],
|
|
||||||
// "theme": "okaidia",
|
|
||||||
"css": true
|
|
||||||
}]
|
|
||||||
],
|
|
||||||
"presets": [
|
|
||||||
"@babel/preset-env",
|
|
||||||
"@babel/preset-react"
|
|
||||||
]
|
|
||||||
}
|
|
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,6 +1,7 @@
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
.netlify
|
.netlify
|
||||||
dist
|
.next
|
||||||
node_modules
|
node_modules
|
||||||
|
out
|
||||||
package-lock.json
|
package-lock.json
|
||||||
tslint.log
|
tslint.log
|
3
.prettierignore
Normal file
3
.prettierignore
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
.netlify
|
||||||
|
.next
|
||||||
|
node_modules
|
@@ -18,7 +18,7 @@ const main = () => {
|
|||||||
const browser = await puppeteer.launch();
|
const browser = await puppeteer.launch();
|
||||||
|
|
||||||
const page = await browser.newPage();
|
const page = await browser.newPage();
|
||||||
await page.goto(`http://localhost:1234/patterns/${pattern}`);
|
await page.goto(`http://localhost:3000/patterns/${pattern}`);
|
||||||
|
|
||||||
await page.waitForSelector('.demo__live');
|
await page.waitForSelector('.demo__live');
|
||||||
const element = await page.$('.demo__live');
|
const element = await page.$('.demo__live');
|
||||||
|
32
components/FooterBlock.tsx
Normal file
32
components/FooterBlock.tsx
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
import { Footer, FooterGroup, FooterLink } from '@1milligram/design';
|
||||||
|
|
||||||
|
export const FooterBlock = () => (
|
||||||
|
<footer className="block-footer">
|
||||||
|
<div className="block-container">
|
||||||
|
<Footer>
|
||||||
|
<FooterGroup title="Products">
|
||||||
|
<FooterLink href="https://blur.page">Blur Page</FooterLink>
|
||||||
|
<FooterLink href="https://formvalidation.io">Form Validation</FooterLink>
|
||||||
|
<FooterLink href="https://intersectionobserver.io">IntersectionObserver Examples</FooterLink>
|
||||||
|
<FooterLink href="https://react-pdf-viewer.dev">React PDF Viewer</FooterLink>
|
||||||
|
</FooterGroup>
|
||||||
|
<FooterGroup title="Open sources">
|
||||||
|
<FooterLink href="https://1loc.dev">1 LOC</FooterLink>
|
||||||
|
<FooterLink href="https://csslayout.io">CSS Layout</FooterLink>
|
||||||
|
<FooterLink href="https://getfrontend.tips">Front-end Tips</FooterLink>
|
||||||
|
<FooterLink href="https://htmldom.dev">HTML DOM</FooterLink>
|
||||||
|
<FooterLink href="https://thisthat.dev">this VS that</FooterLink>
|
||||||
|
</FooterGroup>
|
||||||
|
<FooterGroup title="Follow us">
|
||||||
|
<FooterLink href="https://github.com/1milligram">GitHub</FooterLink>
|
||||||
|
<FooterLink href="https://twitter.com/nghuuphuoc">Twitter</FooterLink>
|
||||||
|
</FooterGroup>
|
||||||
|
</Footer>
|
||||||
|
|
||||||
|
<div className="block-footer__copyright">
|
||||||
|
© 2020 — {new Date().getFullYear()}, 1 milligram. All rights reserved.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
);
|
37
components/HeaderBlock.tsx
Normal file
37
components/HeaderBlock.tsx
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import Link from 'next/link';
|
||||||
|
import * as React from 'react';
|
||||||
|
import { Logo } from '@1milligram/design';
|
||||||
|
|
||||||
|
export const HeaderBlock = () => {
|
||||||
|
const [totalStars, setTotalStars] = React.useState(0);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
fetch('https://api.github.com/repos/1milligram/csslayout')
|
||||||
|
.then((res) => res.json())
|
||||||
|
.then((data) => setTotalStars(data.stargazers_count))
|
||||||
|
.catch(console.log);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const HeaderLogo = React.forwardRef<HTMLAnchorElement, React.LinkHTMLAttributes<HTMLAnchorElement>>(
|
||||||
|
(props, ref) => (
|
||||||
|
<a href={props.href} onClick={props.onClick} ref={ref}>
|
||||||
|
<Logo brand="CSS Layout" />
|
||||||
|
</a>
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<header className="block-header">
|
||||||
|
<div className="block-container">
|
||||||
|
<div className="block-header__inner">
|
||||||
|
<Link href="/" passHref>
|
||||||
|
<HeaderLogo />
|
||||||
|
</Link>
|
||||||
|
<Link href="https://github.com/1milligram/csslayout">
|
||||||
|
<a className="block-header__cta">GitHub {totalStars}★</a>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
);
|
||||||
|
};
|
25
layouts/Layout.tsx
Normal file
25
layouts/Layout.tsx
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import Head from 'next/head';
|
||||||
|
import * as React from 'react';
|
||||||
|
import { FooterBlock } from '../components/FooterBlock';
|
||||||
|
import { HeaderBlock } from '../components/HeaderBlock';
|
||||||
|
|
||||||
|
interface LayoutProps {
|
||||||
|
title: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Layout: React.FC<LayoutProps> = ({ children, title }) => (
|
||||||
|
<>
|
||||||
|
<Head>
|
||||||
|
<title>{title} - CSS Layout</title>
|
||||||
|
<meta name="description" content={title} />
|
||||||
|
<meta name="twitter:title" content={`${title} - CSS Layout`} />
|
||||||
|
<meta name="twitter:description" content={title} />
|
||||||
|
<meta property="og:title" content={`${title} - CSS Layout`} />
|
||||||
|
<meta property="og:description" content={title} />
|
||||||
|
</Head>
|
||||||
|
|
||||||
|
<HeaderBlock />
|
||||||
|
{children}
|
||||||
|
<FooterBlock />
|
||||||
|
</>
|
||||||
|
);
|
6
next-env.d.ts
vendored
Normal file
6
next-env.d.ts
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
/// <reference types="next" />
|
||||||
|
/// <reference types="next/types/global" />
|
||||||
|
/// <reference types="next/image-types/global" />
|
||||||
|
|
||||||
|
// NOTE: This file should not be edited
|
||||||
|
// see https://nextjs.org/docs/basic-features/typescript for more information.
|
9
next.config.js
Normal file
9
next.config.js
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
const withMDX = require('@next/mdx')({
|
||||||
|
extension: /\.mdx?$/,
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = withMDX({
|
||||||
|
// `true` will transform `/about` to `/about/index.html`
|
||||||
|
trailingSlash: true,
|
||||||
|
pageExtensions: ['js', 'jsx', 'tsx', 'mdx'],
|
||||||
|
});
|
88
package.json
88
package.json
@@ -1,61 +1,61 @@
|
|||||||
{
|
{
|
||||||
"name": "csslayout",
|
"name": "csslayout",
|
||||||
|
"description": "A collection of popular layouts and patterns made with CSS",
|
||||||
|
"author": {
|
||||||
|
"name": "Nguyen Huu Phuoc",
|
||||||
|
"email": "me@phuoc.ng",
|
||||||
|
"url": "https://twitter.com/nghuuphuoc"
|
||||||
|
},
|
||||||
|
"homepage": "https://csslayout.io",
|
||||||
|
"keywords": [
|
||||||
|
"CSS grid",
|
||||||
|
"CSS flexbox",
|
||||||
|
"CSS layout",
|
||||||
|
"CSS patterns"
|
||||||
|
],
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/1milligram/csslayout"
|
||||||
|
},
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/1milligram/csslayout/issues"
|
||||||
|
},
|
||||||
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"copy": "rimraf dist && mkdir dist && cpx 'public/**/*' dist",
|
"build": "next build",
|
||||||
"dev": "npm run copy && webpack --mode=development",
|
"dev": "next dev",
|
||||||
"dev-server": "npm run copy && NODE_ENV=development webpack serve",
|
"format": "prettier --write \"**/*.+(css|html|json|js|jsx|mdx|scss|ts|tsx)\"",
|
||||||
"build": "npm run copy && webpack --mode=production && npm run export",
|
"preexport": "npm run build",
|
||||||
"export": "react-snap",
|
"export": "next export",
|
||||||
"deploy": "npm run build && netlify deploy --dir=dist --prod",
|
"deploy": "npm run export && netlify deploy --prod --dir=out",
|
||||||
"analyse": "NODE_ENV=analyse webpack --config webpack.config.js -p",
|
|
||||||
"lint": "tslint -c tslint.json -o tslint.log 'client/**/*.{ts,tsx}'",
|
"lint": "tslint -c tslint.json -o tslint.log 'client/**/*.{ts,tsx}'",
|
||||||
"screenshot": "TS_NODE_COMPILER_OPTIONS='{\"module\":\"commonjs\"}' ts-node bin/generateScreenshot.ts"
|
"screenshot": "TS_NODE_COMPILER_OPTIONS='{\"module\":\"commonjs\"}' ts-node bin/generateScreenshot.ts"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@loadable/component": "^5.14.1",
|
"@loadable/component": "^5.14.1",
|
||||||
"prismjs": "^1.23.0",
|
"@1milligram/design": "^0.4.0",
|
||||||
|
"@1milligram/frame": "^1.0.0",
|
||||||
|
"@mdx-js/loader": "^1.6.22",
|
||||||
|
"@mdx-js/react": "^1.6.22",
|
||||||
|
"@next/mdx": "^11.1.2",
|
||||||
|
"next": "^11.1.2",
|
||||||
|
"prism-react-renderer": "^1.2.1",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2"
|
||||||
"react-helmet": "^6.1.0",
|
|
||||||
"react-router-dom": "^5.2.0"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.13.13",
|
"@types/linkifyjs": "^2.1.4",
|
||||||
"@babel/preset-env": "^7.13.12",
|
|
||||||
"@babel/preset-react": "^7.13.13",
|
|
||||||
"@loadable/babel-plugin": "^5.13.2",
|
|
||||||
"@types/loadable__component": "^5.13.3",
|
"@types/loadable__component": "^5.13.3",
|
||||||
"@types/prismjs": "^1.16.4",
|
"@types/react": "^17.0.20",
|
||||||
"@types/react": "^17.0.3",
|
"@types/react-dom": "^17.0.9",
|
||||||
"@types/react-dom": "^17.0.3",
|
"puppeteer": "^10.4.0",
|
||||||
"@types/react-helmet": "^6.1.0",
|
"prettier": "^2.4.0",
|
||||||
"@types/react-router-dom": "^5.1.7",
|
"sass": "^1.39.2",
|
||||||
"babel-loader": "^8.2.2",
|
"serve": "^12.0.1",
|
||||||
"babel-plugin-prismjs": "^2.0.1",
|
"typescript": "^4.4.3",
|
||||||
"cpx2": "^3.0.0",
|
|
||||||
"css-loader": "^5.2.0",
|
|
||||||
"html-webpack-plugin": "^5.3.1",
|
|
||||||
"mini-css-extract-plugin": "^1.4.0",
|
|
||||||
"puppeteer": "^1.20.0",
|
|
||||||
"react-snap": "^1.23.0",
|
|
||||||
"rimraf": "^3.0.2",
|
|
||||||
"source-map-loader": "^2.0.1",
|
|
||||||
"style-loader": "^2.0.0",
|
|
||||||
"ts-loader": "^8.1.0",
|
"ts-loader": "^8.1.0",
|
||||||
"ts-node": "^9.1.1",
|
"ts-node": "^9.1.1",
|
||||||
"tslint": "^6.1.3",
|
"tslint": "^6.1.3",
|
||||||
"tslint-react": "^5.0.0",
|
"tslint-react": "^5.0.0"
|
||||||
"typescript": "^4.2.3",
|
|
||||||
"webpack": "^5.28.0",
|
|
||||||
"webpack-bundle-analyzer": "^4.4.0",
|
|
||||||
"webpack-cli": "^4.6.0",
|
|
||||||
"webpack-dev-server": "^3.11.2"
|
|
||||||
},
|
|
||||||
"reactSnap": {
|
|
||||||
"source": "dist",
|
|
||||||
"minifyHtml": {
|
|
||||||
"collapseWhitespace": false,
|
|
||||||
"removeComments": false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
17
pages/_app.tsx
Normal file
17
pages/_app.tsx
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import Head from 'next/head';
|
||||||
|
|
||||||
|
// Design
|
||||||
|
import '@1milligram/design/lib/styles/index.css';
|
||||||
|
import '@1milligram/frame/lib/styles/index.css';
|
||||||
|
import '../styles/index.scss';
|
||||||
|
|
||||||
|
export default function MyApp({ Component, pageProps }) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Head>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
</Head>
|
||||||
|
<Component {...pageProps} />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
44
pages/_document.tsx
Normal file
44
pages/_document.tsx
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import Document, { Html, Head, Main, NextScript } from 'next/document';
|
||||||
|
|
||||||
|
class MyDocument extends Document {
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<Html>
|
||||||
|
<Head>
|
||||||
|
<link href="/favicon.png" rel="icon" />
|
||||||
|
<meta charSet="utf-8" />
|
||||||
|
|
||||||
|
<meta content="A collection of popular layouts and patterns made with CSS" name="description" />
|
||||||
|
<meta content="CSS flexbox, CSS grid, CSS layout, CSS patterns" name="keywords" />
|
||||||
|
<meta content="Nguyen Huu Phuoc" name="author" />
|
||||||
|
<meta content="@nghuuphuoc" name="twitter:site" />
|
||||||
|
<meta content="summary" name="twitter:card" />
|
||||||
|
<meta content="A collection of popular layouts and patterns made with CSS" name="twitter:description" />
|
||||||
|
<meta content="A collection of popular layouts and patterns made with CSS" name="twitter:title" />
|
||||||
|
<meta content="/assets/logo.png" name="twitter:image" />
|
||||||
|
|
||||||
|
<meta content="A collection of popular layouts and patterns made with CSS" property="og:title" />
|
||||||
|
<meta content="A collection of popular layouts and patterns made with CSS" property="og:description" />
|
||||||
|
<meta content="article" property="og:type" />
|
||||||
|
<meta content="https://csslayout.io" property="og:url" />
|
||||||
|
<meta content="/assets/logo.png" property="og:image" />
|
||||||
|
<meta content="CSS Layout" property="og:site_name" />
|
||||||
|
|
||||||
|
<link rel="icon" href="/assets/favicon.png" />
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="true" />
|
||||||
|
<link
|
||||||
|
rel="stylesheet"
|
||||||
|
href="https://fonts.googleapis.com/css2?&family=Source+Code+Pro:wght@400&family=Inter:wght@400;700&display=swap"
|
||||||
|
/>
|
||||||
|
</Head>
|
||||||
|
<body>
|
||||||
|
<Main />
|
||||||
|
<NextScript />
|
||||||
|
</body>
|
||||||
|
</Html>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MyDocument;
|
13
pages/index.tsx
Normal file
13
pages/index.tsx
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
|
import { Layout } from '../layouts/Layout';
|
||||||
|
|
||||||
|
const HomePage = () => {
|
||||||
|
return (
|
||||||
|
<Layout title="A collection of popular layouts and patterns made with CSS">
|
||||||
|
|
||||||
|
</Layout>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default HomePage;
|
5
prettier.config.js
Normal file
5
prettier.config.js
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
module.exports = {
|
||||||
|
printWidth: 120,
|
||||||
|
singleQuote: true,
|
||||||
|
tabWidth: 4,
|
||||||
|
};
|
30
styles/_reset.scss
Normal file
30
styles/_reset.scss
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
body {
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
color: #333;
|
||||||
|
font-family: 'Inter', sans-serif;
|
||||||
|
line-height: 1.5;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
* {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
img {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
ol,
|
||||||
|
ul {
|
||||||
|
list-style-type: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
11
styles/blocks/_footer.scss
Normal file
11
styles/blocks/_footer.scss
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
/* Footer */
|
||||||
|
.block-footer {
|
||||||
|
border-top: 1px solid #e1e1e1;
|
||||||
|
padding-top: 4rem;
|
||||||
|
}
|
||||||
|
.block-footer__copyright {
|
||||||
|
color: #afafaf;
|
||||||
|
margin: 2rem 0 4rem 0;
|
||||||
|
padding: 1rem 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
23
styles/blocks/_header.scss
Normal file
23
styles/blocks/_header.scss
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
.block-header {
|
||||||
|
background: #fff;
|
||||||
|
border-bottom: 1px solid #e4e4e4;
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
z-index: 9999;
|
||||||
|
}
|
||||||
|
.block-header__inner {
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
height: 3rem;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
.block-header__cta {
|
||||||
|
align-items: center;
|
||||||
|
background-color: var(--mgd-color-primary);
|
||||||
|
border-radius: 9999px;
|
||||||
|
color: #fff;
|
||||||
|
display: flex;
|
||||||
|
font-weight: 600;
|
||||||
|
height: 2rem;
|
||||||
|
padding: 0 1.5rem;
|
||||||
|
}
|
13
styles/blocks/_layout.scss
Normal file
13
styles/blocks/_layout.scss
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
.block-container {
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
max-width: 64rem;
|
||||||
|
}
|
||||||
|
.block-hero {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.block-hero__heading--secondary {
|
||||||
|
color: #808080;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
6
styles/index.scss
Normal file
6
styles/index.scss
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
@import './reset';
|
||||||
|
|
||||||
|
// Blocks
|
||||||
|
@import 'blocks/footer';
|
||||||
|
@import 'blocks/header';
|
||||||
|
@import 'blocks/layout';
|
@@ -1,12 +1,32 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"outDir": "./dist/",
|
"outDir": "./dist/",
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"noImplicitAny": true,
|
"noImplicitAny": true,
|
||||||
"module": "esnext",
|
"module": "esnext",
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"target": "esnext",
|
"target": "esnext",
|
||||||
"jsx": "react"
|
"jsx": "preserve",
|
||||||
}
|
"lib": [
|
||||||
|
"dom",
|
||||||
|
"dom.iterable",
|
||||||
|
"esnext"
|
||||||
|
],
|
||||||
|
"allowJs": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"strict": false,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"isolatedModules": true
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"next-env.d.ts",
|
||||||
|
"**/*.ts",
|
||||||
|
"**/*.tsx"
|
||||||
|
],
|
||||||
|
"exclude": [
|
||||||
|
"node_modules"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
@@ -1,78 +0,0 @@
|
|||||||
/**
|
|
||||||
* A collection of popular layouts and patterns made with CSS (https://csslayout.io)
|
|
||||||
* (c) 2019 - 2021 Nguyen Huu Phuoc <https://twitter.com/nghuuphuoc>
|
|
||||||
*/
|
|
||||||
|
|
||||||
const path = require('path');
|
|
||||||
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
|
|
||||||
const HtmlWebPackPlugin = require("html-webpack-plugin");
|
|
||||||
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
|
||||||
|
|
||||||
const plugins = [
|
|
||||||
new HtmlWebPackPlugin({
|
|
||||||
template: './client/index.html',
|
|
||||||
filename: './index.html',
|
|
||||||
}),
|
|
||||||
new MiniCssExtractPlugin({
|
|
||||||
filename: '[name].[contenthash].css',
|
|
||||||
ignoreOrder: false, // Enable to remove warnings about conflicting order
|
|
||||||
}),
|
|
||||||
];
|
|
||||||
|
|
||||||
if (process.env.NODE_ENV === "analyse") {
|
|
||||||
plugins.push(new BundleAnalyzerPlugin());
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
mode: process.env.NODE_ENV,
|
|
||||||
entry: {
|
|
||||||
client: './client/index.tsx',
|
|
||||||
},
|
|
||||||
output: {
|
|
||||||
path: path.join(__dirname, 'dist'),
|
|
||||||
filename: '[name].[contenthash].js',
|
|
||||||
// If user browser enables ad blocking, then the pattern likes `Cookie banner` can't be loaded
|
|
||||||
// In order to fix that, we remove the `[name]` from the bundled output
|
|
||||||
chunkFilename: '[contenthash].js',
|
|
||||||
// It's very important
|
|
||||||
// All the chunk generated by webpack then will be loaded such as
|
|
||||||
// <script charset="utf-8" src="/[chunk-name].bundle.js"></script>
|
|
||||||
// The script is accessible from any page that exported by a 3rd party such as react-snap
|
|
||||||
publicPath: '/',
|
|
||||||
},
|
|
||||||
module: {
|
|
||||||
rules: [
|
|
||||||
{
|
|
||||||
test: /\.css$/,
|
|
||||||
use: [
|
|
||||||
{
|
|
||||||
loader: MiniCssExtractPlugin.loader,
|
|
||||||
},
|
|
||||||
'css-loader',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.ts(x?)$/,
|
|
||||||
exclude: /node_modules/,
|
|
||||||
// The order of loaders are very important
|
|
||||||
// It will make the @loadable/component work
|
|
||||||
use: ['babel-loader', 'ts-loader'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
enforce: "pre",
|
|
||||||
test: /\.js$/,
|
|
||||||
loader: 'source-map-loader',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
resolve: {
|
|
||||||
extensions: ['.js', '.jsx', '.ts', '.tsx'],
|
|
||||||
},
|
|
||||||
devtool: process.env.NODE_ENV === 'production' ? false : 'source-map',
|
|
||||||
devServer: {
|
|
||||||
contentBase: path.join(__dirname, 'dist'),
|
|
||||||
historyApiFallback: true,
|
|
||||||
port: 1234,
|
|
||||||
},
|
|
||||||
plugins,
|
|
||||||
};
|
|
Reference in New Issue
Block a user