Skip to content

Commit

Permalink
fix(webpack): seamless css support for all frameworks 🎉
Browse files Browse the repository at this point in the history
  • Loading branch information
JounQin committed Oct 29, 2019
1 parent 2f23f83 commit 75bcf4a
Show file tree
Hide file tree
Showing 12 changed files with 630 additions and 46 deletions.
18 changes: 11 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,23 @@
"build:r": "ts-node --files packages/rollup/src/cli -e named --exclude utils -p",
"build:ts": "tsc -b",
"build:w": "rimraf dist && run-p build:w:*",
"build:w:angular": "ts-node --files packages/webpack/src/cli -e src/angular -o dist/angular -t angular -p",
"build:w:react": "ts-node --files packages/webpack/src/cli -e src/react -o dist/react -t react -p",
"build:w:vue": "ts-node --files packages/webpack/src/cli -e src/vue -o dist/vue -t vue -p",
"build:w:angular": "yarn w:build -o dist/angular -t angular -p",
"build:w:react": "yarn w:build -e src/react -o dist/react -t react -p",
"build:w:vue": "yarn w:build -e src/vue -o dist/vue -t vue -p",
"clean": "rimraf packages/*/{lib,*.tsbuildinfo}",
"debug": "cross-env DEBUG=w:* yarn dev:angular",
"dev:angular": "ts-node -T --files packages/webpack/src/cli -e src/angular -t angular",
"dev:react": "ts-node -T --files packages/webpack/src/cli -e src/react -t react",
"dev:vue": "ts-node -T --files packages/webpack/src/cli -e src/vue -t vue",
"dev:angular": "yarn w:dev -e src/angular -t angular",
"dev:react": "yarn w:dev -e src/react -t react",
"dev:vue": "yarn w:dev -e src/vue -t vue",
"lint": "run-p lint:*",
"lint:es": "cross-env PARSER_NO_WATCH=true eslint . --cache --ext js,md,ts -f friendly",
"lint:ts": "tslint -p . -t stylish",
"pretest": "lerna run build && yarn clean",
"serve": "serve dist",
"test": "jest",
"type-coverage": "type-coverage --cache --detail --ignore-files *.d.ts --strict"
"type-coverage": "type-coverage --cache --detail --ignore-files *.d.ts --strict",
"w:build": "ts-node --files packages/webpack/src/cli",
"w:dev": "ts-node -T --files packages/webpack/src/cli"
},
"devDependencies": {
"@1stg/babel-preset": "^0.7.10",
Expand Down Expand Up @@ -64,6 +66,7 @@
"@types/lodash": "^4.14.144",
"@types/mini-css-extract-plugin": "^0.8.0",
"@types/node": "^12.11.7",
"@types/postcss-load-config": "^2.0.0",
"@types/prettier": "^1.18.3",
"@types/react": "^16.9.11",
"@types/react-dom": "^16.9.3",
Expand All @@ -75,6 +78,7 @@
"@types/webpack-dev-server": "^3.4.0",
"@types/webpack-env": "^1.14.1",
"@types/workbox-webpack-plugin": "^4.1.0",
"core-js": "^3.3.5",
"eslint": "^6.6.0",
"fbjs": "^1.0.0",
"husky": "^3.0.9",
Expand Down
15 changes: 9 additions & 6 deletions packages/utils/src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,16 @@ export const isMdxAvailable =

export const isVueAvailable = isPkgAvailable('vue')

export const tryFile = (filePath?: string | string[]) => {
export const tryFile = (filePath?: string | string[], includeDir?: boolean) => {
if (typeof filePath === 'string') {
return fs.existsSync(filePath) ? filePath : ''
return fs.existsSync(filePath) &&
(includeDir || fs.statSync(filePath).isFile())
? filePath
: ''
}

for (const file of filePath || []) {
if (tryFile(file)) {
if (tryFile(file, includeDir)) {
return file
}
}
Expand All @@ -37,8 +40,8 @@ export const tryFile = (filePath?: string | string[]) => {
}

export const tryExtensions = (filepath: string, extensions = EXTENSIONS) => {
const ext = extensions.concat('').find(ext => fs.existsSync(filepath + ext))
return ext ? filepath + ext : ''
const ext = extensions.concat('').find(ext => tryFile(filepath + ext))
return ext == null ? '' : filepath + ext
}

export const identify = <T>(
Expand All @@ -52,7 +55,7 @@ export const findUp = (searchEntry: string, searchFile = 'package.json') => {
console.assert(path.isAbsolute(searchEntry))

if (
!tryFile(searchEntry) ||
!tryFile(searchEntry, true) ||
(searchEntry !== CWD && !searchEntry.startsWith(CWD + path.sep))
) {
return ''
Expand Down
1 change: 1 addition & 0 deletions packages/webpack/.config/.postcssrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('@1stg/postcss-config')
6 changes: 6 additions & 0 deletions packages/webpack/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
],
"dependencies": {
"@1stg/babel-preset": "^0.7.10",
"@1stg/postcss-config": "^0.3.5",
"@babel/core": "^7.6.4",
"@hot-loader/react-dom": "^16.10.2",
"@mdx-js/loader": "^1.5.1",
Expand All @@ -34,6 +35,7 @@
"copy-webpack-plugin": "^5.0.4",
"css-loader": "^3.2.0",
"debug": "^4.1.1",
"exports-loader": "^0.7.0",
"file-loader": "^4.2.0",
"friendly-errors-webpack-plugin": "^2.0.0-beta.2",
"html-loader": "^0.5.5",
Expand All @@ -46,10 +48,14 @@
"less-loader": "^5.0.0",
"lodash": "^4.17.15",
"mini-css-extract-plugin": "^0.8.0",
"postcss": "^7.0.21",
"postcss-load-config": "^2.1.0",
"postcss-loader": "^3.0.0",
"pug": "^2.0.4",
"pug-loader": "^2.4.0",
"pug-plain-loader": "^1.0.0",
"react-hot-loader": "^4.12.15",
"raw-loader": "^3.1.0",
"sass": "^1.23.1",
"sass-loader": "^8.0.0",
"style-loader": "^1.0.0",
Expand Down
71 changes: 54 additions & 17 deletions packages/webpack/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { alias } from '@pkgr/es-modules'
import {
DEV,
EXTENSIONS,
NODE_ENV,
NODE_MODULES_REG,
PROD,
__DEV__,
Expand All @@ -26,7 +27,8 @@ import HtmlWebpackInlineSourcePlugin from 'html-webpack-inline-source-plugin'
import HtmlWebpackPlugin from 'html-webpack-plugin'
import LazyCompileWebpackPlugin from 'lazy-compile-webpack-plugin'
import MiniCssExtractPlugin from 'mini-css-extract-plugin'
import { resolve } from 'path'
import { resolve, sep } from 'path'
import { sync } from 'postcss-load-config'
import TsconfigPathsWebpackPlugin from 'tsconfig-paths-webpack-plugin'
import { VueLoaderPlugin } from 'vue-loader'
import webpack, { Configuration } from 'webpack'
Expand All @@ -48,7 +50,7 @@ export interface ConfigOptions {
prod?: boolean
}

let tsconfigFile = tryFile([
const baseTsconfigFile = tryFile([
'tsconfig.app.json',
'tsconfig.base.json',
'tsconfig.json',
Expand All @@ -61,6 +63,8 @@ const extraLoaderOptions: Record<string, {}> = {
},
}

const configsPath = resolve(__dirname, '../.config')

export default ({
entry = 'src',
outputDir = 'dist',
Expand All @@ -78,18 +82,12 @@ export default ({
const react = type === 'react' || (!type && isReactAvailable)
const vue = type === 'vue' || (!type && isVueAvailable)

const pkgFile = findUp(entry)

// eslint-disable-next-line @typescript-eslint/no-require-imports
const pkg: Record<string, string> = pkgFile ? require(pkgFile) : {}

const hashType = prod ? 'contenthash' : 'hash'
const filenamePrefix = `[name].[${hashType}].`

const sourceMap = !prod

if (prod) {
tsconfigFile = tryFile('tsconfig.prod.json') || tsconfigFile
}
const tsconfigFile = tryFile('tsconfig.prod.json') || baseTsconfigFile

const baseBabelLoader = {
loader: 'babel-loader',
Expand All @@ -111,10 +109,37 @@ export default ({

const babelLoader = ['cache-loader', 'thread-loader', baseBabelLoader]

let postcssConfig:
| {
path: string
ctx: {
env: string
}
}
| undefined

const postcssCtx = {
env: prod ? PROD : NODE_ENV,
}

try {
postcssConfig = {
path: resolve(sync(postcssCtx).file, '..') + sep,
ctx: postcssCtx,
}
} catch {
postcssConfig = {
path: configsPath + sep,
ctx: postcssCtx,
}
}

const baseCssLoaders = (modules = false, extraLoader?: string) =>
[
prod
? MiniCssExtractPlugin.loader
: angular
? 'exports-loader?exports.toString()'
: vue
? 'vue-style-loader'
: 'style-loader',
Expand All @@ -136,10 +161,11 @@ export default ({
loader: 'postcss-loader',
options: {
sourceMap,
config: postcssConfig,
},
},
extraLoader && {
loader: extraLoader,
loader: extraLoader + '-loader',
options: {
...extraLoaderOptions[extraLoader],
sourceMap,
Expand All @@ -153,7 +179,7 @@ export default ({
use: baseCssLoaders(false, extraLoader),
},
{
use: baseCssLoaders(true, extraLoader),
use: baseCssLoaders(!angular, extraLoader),
},
]

Expand All @@ -163,6 +189,11 @@ export default ({
tryExtensions(resolve(entry, '../index'), ['.pug', '.html', '.ejs']) ||
resolve(__dirname, '../index.pug')

const pkgFile = findUp(entry)

// eslint-disable-next-line @typescript-eslint/no-require-imports
const pkg: Record<string, string> = pkgFile ? require(pkgFile) : {}

const config: Configuration = {
mode: prod ? PROD : DEV,
devtool: !prod && 'cheap-module-eval-source-map',
Expand Down Expand Up @@ -199,7 +230,7 @@ export default ({
].filter(identify),
},
output: {
filename: `[name].[${hashType}].js`,
filename: filenamePrefix + 'js',
path: resolve(outputDir),
},
module: {
Expand Down Expand Up @@ -279,8 +310,12 @@ export default ({
loader: 'pug-loader',
},
{
resourceQuery: /^\?vue/,
loader: 'pug-plain-loader',
},
{
use: ['raw-loader', 'pug-plain-loader'],
},
],
},
].filter(identify),
Expand All @@ -302,7 +337,9 @@ export default ({
}),
new CaseSensitivePathsWebpackPlugin(),
new CopyWebpackPlugin(
copies.concat(tryFile(resolve(entry, '../public'))).filter(identify),
copies
.concat(tryFile(resolve(entry, '../public'), true))
.filter(identify),
),
new FriendlyErrorsWebpackPlugin(),
prod &&
Expand All @@ -326,10 +363,10 @@ export default ({
minify: prod as false,
}),
new HtmlWebpackHarddiskPlugin(),
new HtmlWebpackInlineSourcePlugin(),
!prod && new LazyCompileWebpackPlugin(),
prod && new HtmlWebpackInlineSourcePlugin(),
__DEV__ && new LazyCompileWebpackPlugin(),
new MiniCssExtractPlugin({
filename: `[name].[${hashType}].css`,
filename: filenamePrefix + 'css',
}),
vue && new VueLoaderPlugin(),
].filter(identify),
Expand Down
1 change: 1 addition & 0 deletions src/angular/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"@1stg/prettier-config/angular"
2 changes: 2 additions & 0 deletions src/angular/app.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Hello World!
<span class="counter">{{ counter$ | async }}</span>
3 changes: 3 additions & 0 deletions src/angular/app.component.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.counter {
color: red;
}
21 changes: 15 additions & 6 deletions src/angular/app.component.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
import { Component } from '@angular/core'
import { Component, OnDestroy } from '@angular/core'
import { Subject, interval } from 'rxjs'
import { takeUntil } from 'rxjs/operators'

@Component({
selector: '#app',
template: `
Hello World
`,
templateUrl: 'app.component.html',
styleUrls: ['app.component.scss'],
})
// eslint-disable-next-line @typescript-eslint/no-extraneous-class
export class AppComponent {}
export class AppComponent implements OnDestroy {
destroy$ = new Subject<void>()

counter$ = interval(1000).pipe(takeUntil(this.destroy$))

ngOnDestroy() {
this.destroy$.next()
this.destroy$.complete()
}
}
1 change: 1 addition & 0 deletions src/vue/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"@1stg/prettier-config/vue"
2 changes: 1 addition & 1 deletion tslint.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"extends": "@1stg/tslint-config/eslint",
"linterOptions": {
"exclude": [
"**/lib.**",
"**/lib/**",
"**/node_modules/**",
"packages/named-exports/index.ts"
]
Expand Down
Loading

0 comments on commit 75bcf4a

Please sign in to comment.