Skip to content

Commit

Permalink
feat: ✨cssmodule auto
Browse files Browse the repository at this point in the history
  • Loading branch information
huruji committed Aug 31, 2020
1 parent 742abce commit 459cc73
Show file tree
Hide file tree
Showing 12 changed files with 914 additions and 153 deletions.
601 changes: 551 additions & 50 deletions packages/cli/package-lock.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,12 @@
"commander": "^2.20.0",
"cosmiconfig": "^6.0.0",
"css-loader": "^1.0.1",
"css-modules-typescript-loader": "^4.0.0",
"cssnano": "^4.1.10",
"download-npm-package": "^3.1.12",
"es5-imcompatible-versions": "^0.1.57",
"escape-string-regexp": "^2.0.0",
"extract-css-chunks-webpack-plugin": "^4.7.5",
"get-port": "^5.0.0",
"gh-clone": "^2.0.1",
"git-clone-repo": "^1.0.0",
Expand Down
3 changes: 2 additions & 1 deletion packages/cli/src/compiler/utils/defaultConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ const defaultConfig: SasoConfig = {
fileHash: true,
extraCss: true,
globalConfig: {},
extraBabelIncludes: []
extraBabelIncludes: [],
cssmodule: true
}

export default defaultConfig
29 changes: 29 additions & 0 deletions packages/cli/src/plugins/css-plugin/css.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import WebpackChain from 'webpack-chain'
import { applyRule } from './util'

function after(rule: WebpackChain.Rule): void {
}

export default (config: WebpackChain): void => {
const { cssmodule } = config.sasoConfig
const isProd = config.toConfig().mode === 'production'

const rule = config.module.rule('compile scss').test(/\.css$/)
rule.exclude.add(/\.module/)

const ruleWithModules = config.module.rule('compile scss with module').test(/\.module\.css$/)

applyRule({
rule: ruleWithModules,
config,
isCssModules: true,
after,
})

applyRule({
rule,
config,
isCssModules: false,
after
})
}
114 changes: 12 additions & 102 deletions packages/cli/src/plugins/css-plugin/index.ts
Original file line number Diff line number Diff line change
@@ -1,123 +1,33 @@
import MiniCssExtractPlugin from 'mini-css-extract-plugin'
import FixStyleOnlyEntriesPlugin from 'webpack-fix-style-only-entries'
import { cosmiconfigSync } from 'cosmiconfig'
import * as path from 'path'
import MiniCssExtractPlugin from 'mini-css-extract-plugin'
import { SasoPlugin } from '../../typings/compiler'
import WebpackChain from 'webpack-chain'
import cssRule from './css'
import lessRule from './less'
import sassRule from './sass'
import stylusRule from './styl'

const plugin: SasoPlugin = {
apply(compiler) {
compiler.hook('beforeCompile', (config: WebpackChain) => {
/**
* @type {import('webpack-chain')}
*/
const c = config
const { cssmodule } = c.sasoConfig
const isProd = c.toConfig().mode === 'production'
const postcssConfig = cosmiconfigSync('postcss', {
stopDir: process.cwd()
}).search()

const cssRule = c.module.rule('compile css').test(/\.css$/)
const sassRule = c.module.rule('compile sass').test(/\.s[a|c]ss$/)
const lessRule = c.module.rule('compile less').test(/\.less$/)
const stylusRule = c.module.rule('compile stylus').test(/\.styl(us)?$/)

const postcssOptions = {
config: {
path: postcssConfig ? path.dirname(postcssConfig.filepath) : path.resolve(__dirname, '../../config')
}
}

if (!isProd) {
cssRule.use('vue-style-loader').loader(require.resolve('vue-style-loader'))
sassRule.use('vue-style-loader').loader(require.resolve('vue-style-loader'))
lessRule.use('vue-style-loader').loader(require.resolve('vue-style-loader'))
stylusRule.use('vue-style-loader').loader(require.resolve('vue-style-loader'))
} else {
cssRule.use('css-mini-css').loader(MiniCssExtractPlugin.loader)
sassRule.use('sass-mini-css').loader(MiniCssExtractPlugin.loader)
lessRule.use('less-mini-css').loader(MiniCssExtractPlugin.loader)
stylusRule.use('stylus-mini-css').loader(MiniCssExtractPlugin.loader)
}

if (cssmodule) {
cssRule.use('typings-for-css-modules-loader').loader(require.resolve('typings-for-css-modules-loader')).options({
modules: true,
namedExport: true,
camelCase: true,
localIdentName: '[local]--[hash:base64:5]',
})
sassRule.use('typings-for-css-modules-loader').loader(require.resolve('typings-for-css-modules-loader')).options({
modules: true,
namedExport: true,
camelCase: true,
localIdentName: '[local]--[hash:base64:5]',
})
lessRule.use('typings-for-css-modules-loader').loader(require.resolve('typings-for-css-modules-loader')).options({
modules: true,
namedExport: true,
camelCase: true,
localIdentName: '[local]--[hash:base64:5]',
})
stylusRule.use('typings-for-css-modules-loader').loader(require.resolve('typings-for-css-modules-loader')).options({
modules: true,
namedExport: true,
camelCase: true,
localIdentName: '[local]--[hash:base64:5]',
})
} else {
// set css-loader
cssRule.use('css-loader').loader(require.resolve('css-loader'))
sassRule.use('css-loader').loader(require.resolve('css-loader')).options({
sourceMap: true,
importLoaders: 1
})
lessRule.use('css-loader').loader(require.resolve('css-loader'))
stylusRule.use('css-loader').loader(require.resolve('css-loader'))
}

// set postcss
cssRule.use('css-postcss-loader').loader(require.resolve('postcss-loader')).options(postcssOptions)

sassRule.use('sass-postcss-loader').loader(require.resolve('postcss-loader')).options(postcssOptions)

lessRule.use('less-postcss-loader').loader(require.resolve('postcss-loader')).options(postcssOptions)

stylusRule.use('stylus-postcss-loader').loader(require.resolve('postcss-loader')).options(postcssOptions)

// set sass-loader
sassRule.use('resolve-url-loader').loader(require.resolve('resolve-url-loader')).options({
sourceMap: true,
keepQuery: true,
debug: false
})

sassRule
.use('sass-loader')
.loader(require.resolve('sass-loader'))
.options({
sourceMap: true,
sourceMapContents: false,
implementation: require('sass')
})
.end()

// set less-loader
lessRule.use('less-loader').loader(require.resolve('less-loader')).end()

// set stylus-loader
stylusRule.use('stylus-loader').loader(require.resolve('stylus-loader')).end()
const isProd = config.toConfig().mode === 'production'
sassRule(config)
lessRule(config)
stylusRule(config)
cssRule(config)
const { fileHash, extraCss } = config.sasoConfig
const prodFileName = fileHash ? '[name].[hash].css' : '[name].css'
if (extraCss) {
c.plugin('extra css').use(MiniCssExtractPlugin, [
config.plugin('extra css').use(MiniCssExtractPlugin, [
{
filename: isProd ? prodFileName : '[name].css'
}
])

c.plugin('fix style entry').use(FixStyleOnlyEntriesPlugin)
config.plugin('fix style entry').use(FixStyleOnlyEntriesPlugin)
}
})
}
Expand Down
127 changes: 127 additions & 0 deletions packages/cli/src/plugins/css-plugin/index2.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import * as path from 'path'

import FixStyleOnlyEntriesPlugin from 'webpack-fix-style-only-entries'
import MiniCssExtractPlugin from 'mini-css-extract-plugin'
import { SasoPlugin } from '../../typings/compiler'
import WebpackChain from 'webpack-chain'
import { cosmiconfigSync } from 'cosmiconfig'

const plugin: SasoPlugin = {
apply(compiler) {
compiler.hook('beforeCompile', (config: WebpackChain) => {
/**
* @type {import('webpack-chain')}
*/
const c = config
const { cssmodule } = c.sasoConfig
const isProd = c.toConfig().mode === 'production'
const postcssConfig = cosmiconfigSync('postcss', {
stopDir: process.cwd()
}).search()

const cssRule = c.module.rule('compile css').test(/\.css$/)
const sassRule = c.module.rule('compile sass').test(/\.s[a|c]ss$/)
const lessRule = c.module.rule('compile less').test(/\.less$/)
const stylusRule = c.module.rule('compile stylus').test(/\.styl(us)?$/)

const postcssOptions = {
config: {
path: postcssConfig ? path.dirname(postcssConfig.filepath) : path.resolve(__dirname, '../../config')
}
}

if (!isProd) {
cssRule.use('vue-style-loader').loader(require.resolve('vue-style-loader'))
sassRule.use('vue-style-loader').loader(require.resolve('vue-style-loader'))
lessRule.use('vue-style-loader').loader(require.resolve('vue-style-loader'))
stylusRule.use('vue-style-loader').loader(require.resolve('vue-style-loader'))
} else {
cssRule.use('css-mini-css').loader(MiniCssExtractPlugin.loader)
sassRule.use('sass-mini-css').loader(MiniCssExtractPlugin.loader)
lessRule.use('less-mini-css').loader(MiniCssExtractPlugin.loader)
stylusRule.use('stylus-mini-css').loader(MiniCssExtractPlugin.loader)
}

if (cssmodule) {
cssRule.use('typings-for-css-modules-loader').loader(require.resolve('typings-for-css-modules-loader')).options({
modules: true,
namedExport: true,
camelCase: true,
localIdentName: '[local]--[hash:base64:5]',
})
sassRule.use('typings-for-css-modules-loader').loader(require.resolve('typings-for-css-modules-loader')).options({
modules: true,
namedExport: true,
camelCase: true,
localIdentName: '[local]--[hash:base64:5]',
})
lessRule.use('typings-for-css-modules-loader').loader(require.resolve('typings-for-css-modules-loader')).options({
modules: true,
namedExport: true,
camelCase: true,
localIdentName: '[local]--[hash:base64:5]',
})
stylusRule.use('typings-for-css-modules-loader').loader(require.resolve('typings-for-css-modules-loader')).options({
modules: true,
namedExport: true,
camelCase: true,
localIdentName: '[local]--[hash:base64:5]',
})
} else {
// set css-loader
cssRule.use('css-loader').loader(require.resolve('css-loader'))
sassRule.use('css-loader').loader(require.resolve('css-loader')).options({
sourceMap: true,
importLoaders: 1
})
lessRule.use('css-loader').loader(require.resolve('css-loader'))
stylusRule.use('css-loader').loader(require.resolve('css-loader'))
}

// set postcss
cssRule.use('css-postcss-loader').loader(require.resolve('postcss-loader')).options(postcssOptions)

sassRule.use('sass-postcss-loader').loader(require.resolve('postcss-loader')).options(postcssOptions)

lessRule.use('less-postcss-loader').loader(require.resolve('postcss-loader')).options(postcssOptions)

stylusRule.use('stylus-postcss-loader').loader(require.resolve('postcss-loader')).options(postcssOptions)

// set sass-loader
sassRule.use('resolve-url-loader').loader(require.resolve('resolve-url-loader')).options({
sourceMap: true,
keepQuery: true,
debug: false
})

sassRule
.use('sass-loader')
.loader(require.resolve('sass-loader'))
.options({
sourceMap: true,
sourceMapContents: false,
implementation: require('sass')
})
.end()

// set less-loader
lessRule.use('less-loader').loader(require.resolve('less-loader')).end()

// set stylus-loader
stylusRule.use('stylus-loader').loader(require.resolve('stylus-loader')).end()
const { fileHash, extraCss } = config.sasoConfig
const prodFileName = fileHash ? '[name].[hash].css' : '[name].css'
if (extraCss) {
c.plugin('extra css').use(MiniCssExtractPlugin, [
{
filename: isProd ? prodFileName : '[name].css'
}
])

c.plugin('fix style entry').use(FixStyleOnlyEntriesPlugin)
}
})
}
}

export default plugin
33 changes: 33 additions & 0 deletions packages/cli/src/plugins/css-plugin/index3.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import * as path from 'path'

import FixStyleOnlyEntriesPlugin from 'webpack-fix-style-only-entries'
import MiniCssExtractPlugin from 'mini-css-extract-plugin'
import { SasoPlugin } from '../../typings/compiler'
import WebpackChain from 'webpack-chain'
import { cosmiconfigSync } from 'cosmiconfig'
import sassRule from './sass'

const plugin: SasoPlugin = {
apply(compiler) {
compiler.hook('beforeCompile', (config: WebpackChain) => {
/**
* @type {import('webpack-chain')}
*/
const isProd = config.toConfig().mode === 'production'
sassRule(config)
const { fileHash, extraCss } = config.sasoConfig
const prodFileName = fileHash ? '[name].[hash].css' : '[name].css'
if (extraCss) {
config.plugin('extra css').use(MiniCssExtractPlugin, [
{
filename: isProd ? prodFileName : '[name].css'
}
])

config.plugin('fix style entry').use(FixStyleOnlyEntriesPlugin)
}
})
}
}

export default plugin
30 changes: 30 additions & 0 deletions packages/cli/src/plugins/css-plugin/less.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import WebpackChain from 'webpack-chain'
import { applyRule } from './util'

function after(rule: WebpackChain.Rule): void {
rule.use('less-loader').loader(require.resolve('less-loader')).end()
}

export default (config: WebpackChain): void => {
const { cssmodule } = config.sasoConfig
const isProd = config.toConfig().mode === 'production'

const rule = config.module.rule('compile scss').test(/\.less$/)
rule.exclude.add(/\.module/)

const ruleWithModules = config.module.rule('compile scss with module').test(/\.module\.less$/)

applyRule({
rule: ruleWithModules,
config,
isCssModules: true,
after,
})

applyRule({
rule,
config,
isCssModules: false,
after
})
}
Loading

0 comments on commit 459cc73

Please sign in to comment.