Skip to content

Commit 9a3c9e7

Browse files
authored
refactor: 打包组件不同主题的 css 文件 (#3189)
* refactor: css 文件拆分 * refactor: 主题拆分 * refactor: 主题拆分 * docs: 主题使用的文档更新 * chore: sideEffects 优化 * docs: 更新文档 * feat: 构建 jrkf 主题文件 * chore: 更新模板的跳转路径 * chore: jrfk 变量补齐 * chore: time * fix: review * fix: review * fix: review * fix: review
1 parent 1b91b83 commit 9a3c9e7

File tree

18 files changed

+898
-330
lines changed

18 files changed

+898
-330
lines changed

package.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@
77
"typings": "dist/es/packages/nutui.react.build.d.ts",
88
"sideEffects": [
99
"*.scss",
10-
"dist/es/**/style/*",
11-
"dist/cjs/**/style/*",
12-
"dist/style.css",
13-
"dist/styles/font/*",
14-
"dist/styles/font-jmapp/*"
10+
"dist/es/**/style{,-jmapp,-jrkf}/*",
11+
"dist/cjs/**/style{,-jmapp,-jrkf}/*",
12+
"dist/style{,-jmapp,-jrkf}.css",
13+
"dist/styles/**/*",
14+
"dist/styles/font{,-jmapp,-jrkf}/*"
1515
],
1616
"description": "京东风格的轻量级移动端 React 组件库,支持一套代码生成 H5 和小程序",
1717
"keywords": [
Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,44 @@
11
module.exports = {
2+
webpack: {
3+
module: {
4+
rules: [
5+
{
6+
test: /\.s[ac]ss$/i,
7+
use: [
8+
'style-loader',
9+
'css-loader',
10+
{
11+
loader: "sass-loader",
12+
options: {
13+
additionalData: `@import '@nutui/nutui-react/dist/styles/variables.scss';`
14+
// JDesign 主题
15+
// additionalData: `@import '@nutui/nutui-react/dist/styles/variables-jmapp.scss';`
16+
// JRKF 主题
17+
// additionalData: `@import '@nutui/nutui-react/dist/styles/variables-jrkf.scss';`
18+
},
19+
},
20+
],
21+
},
22+
],
23+
},
24+
},
225
babel: {
326
plugins: [
427
[
5-
"import",
28+
'import',
629
{
7-
"libraryName": "@nutui/nutui-react",
8-
"libraryDirectory": "dist/esm",
9-
"style": "css",
10-
"camel2DashComponentName": false
30+
libraryName: '@nutui/nutui-react',
31+
camel2DashComponentName: false,
32+
customName: (name, file) => {
33+
return `@nutui/nutui-react/dist/es/packages/${name.toLowerCase()}`
34+
},
35+
// 自动加载 scss 样式文件
36+
customStyleName: (name) => `@nutui/nutui-react/dist/es/packages/${name.toLowerCase()}/style`
37+
// 自动加载 css 样式文件
38+
// customStyleName: (name) => `@nutui/nutui-react/dist/es/packages/${name.toLowerCase()}/style`
1139
},
12-
"nutui-react"
13-
]
40+
'nutui-react',
41+
],
1442
]
1543
},
1644
};

packages/nutui-templates/create-app-demo/package.json

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,6 @@
1919
"test": "craco build"
2020
},
2121
"eslintConfig": {
22-
"extends": [
23-
"react-app",
24-
"react-app/jest"
25-
]
2622
},
2723
"browserslist": {
2824
"production": [

packages/nutui-templates/create-app-demo/src/App.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
import React from 'react'
2+
import '@nutui/nutui-react/dist/styles/themes/default.css'
3+
// import '@nutui/nutui-react/dist/styles/themes/jmapp.css'
4+
// import '@nutui/nutui-react/dist/styles/themes/jrkf.css'
25
import './App.css'
36
import { Star } from '@nutui/icons-react'
47
import { Row, Col, Image, Button } from '@nutui/nutui-react'

packages/nutui-templates/vite-demo/package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,13 @@
2020
"@types/react-dom": "^18.2.7",
2121
"@typescript-eslint/eslint-plugin": "^6.0.0",
2222
"@typescript-eslint/parser": "^6.0.0",
23-
"@vitejs/plugin-react": "^4.0.4",
23+
"@vitejs/plugin-react-swc": "^3.5.0",
2424
"eslint": "^8.45.0",
2525
"eslint-plugin-react-hooks": "^4.6.0",
2626
"eslint-plugin-react-refresh": "^0.4.3",
27-
"typescript": "^5.0.2",
28-
"vite": "^4.4.5",
27+
"sass-embedded": "^1.86.3",
28+
"typescript": "~5.6.2",
29+
"vite": "^6.0.5",
2930
"vite-plugin-imp": "^2.4.0"
3031
}
3132
}

packages/nutui-templates/vite-demo/src/App.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import './App.css'
22
import { Star } from '@nutui/icons-react'
33
import { Row, Col, Image, Button } from '@nutui/nutui-react'
4+
import '@nutui/nutui-react/dist/styles/themes/default.css'
5+
// import '@nutui/nutui-react/dist/styles/themes/jmapp.css'
6+
// import '@nutui/nutui-react/dist/styles/themes/jrkf.css'
47

58
const Home = () => {
69
return (
Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { defineConfig } from 'vite'
2-
import react from '@vitejs/plugin-react'
32
import vitePluginImp from 'vite-plugin-imp'
3+
import react from '@vitejs/plugin-react-swc'
44

55
// https://vitejs.dev/config/
66
export default defineConfig({
@@ -11,12 +11,24 @@ export default defineConfig({
1111
{
1212
libName: '@nutui/nutui-react',
1313
style: (name) => {
14-
return `@nutui/nutui-react/dist/esm/${name}/style/css`
14+
return `@nutui/nutui-react/dist/es/packages/${name.toLowerCase()}/style/index`
15+
// return `@nutui/nutui-react/dist/es/packages/${name.toLowerCase()}/style-jmapp/index`
16+
// return `@nutui/nutui-react/dist/es/packages/${name.toLowerCase()}/style-jmapp/index`
1517
},
1618
replaceOldImport: false,
1719
camel2DashComponentName: false,
18-
}
19-
]
20-
})
20+
},
21+
],
22+
}),
2123
],
24+
css: {
25+
preprocessorOptions: {
26+
scss: {
27+
api: 'modern-compiler', // 或 "modern","legacy"
28+
additionalData: `@import '@nutui/nutui-react/dist/styles/variables.scss';`
29+
// jmapp 需要在 app 入口引入 import '@nutui/nutui-react/dist/styles/themes/jmapp.css'
30+
// additionalData: `@import '@nutui/nutui-react/dist/styles/variables-jmapp.scss';`
31+
}
32+
}
33+
},
2234
})

scripts/build-taro.mjs

Lines changed: 77 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -244,26 +244,28 @@ async function buildUMD() {
244244
})
245245
}
246246

247-
async function buildAllCSS() {
247+
// 针对不同主题构建全量的 style
248+
async function buildAllCSS(themeName = '') {
248249
// 拷贝styles
250+
const themeStylePath = themeName ? `style-${themeName}` : 'style'
249251
async function generateAllStyles() {
250-
const projectID = process.env.VITE_APP_PROJECT_ID
251252
const content = [
252-
`@import './styles/variables${projectID ? `-${projectID}` : ''}.scss';`,
253+
`@import './styles/variables${themeName ? `-${themeName}` : ''}.scss';`,
253254
`@import './styles/mixins/index.scss';`,
254255
`@import './styles/animation/index.scss';`,
255256
]
256-
const scssFiles = await glob([`${dist}/es/packages/**/*.scss`])
257+
const scssFiles = await glob([`${dist}/es/packages/**/${themeStylePath}/*.scss`])
257258
scssFiles.forEach((file) => {
258259
content.push(
259-
`@import '${relativePath('/' + file, `/${dist}/style.scss`)}';`,
260+
`@import '${relativePath('/' + file, `/${dist}/${themeStylePath}.scss`)}';`,
260261
)
261262
})
262-
dest(`${dist}/style.scss`, content.join('\n'))
263+
await dest(`${dist}/${themeStylePath}.scss`, content.join('\n'))
263264
}
264265

265266
await generateAllStyles()
266267
await vite.build({
268+
configFile: false,
267269
logLevel: 'error',
268270
resolve: {
269271
alias: [{ find: '@', replacement: resolve(__dirname, '../src') }],
@@ -272,11 +274,16 @@ async function buildAllCSS() {
272274
emptyOutDir: false,
273275
outDir: dist,
274276
lib: {
275-
entry: `./${dist}/style.scss`,
277+
entry: `./${dist}/${themeStylePath}.scss`,
276278
formats: ['es'],
277279
name: 'style',
278280
fileName: 'style',
279281
},
282+
rollupOptions: {
283+
output: {
284+
assetFileNames: `${themeStylePath}.css`, // 资源文件名
285+
}
286+
}
280287
},
281288
})
282289
}
@@ -287,6 +294,11 @@ async function buildThemeCSS() {
287294
})
288295
const projectID = process.env.VITE_APP_PROJECT_ID
289296
const inputFiles = {}
297+
// nuitui 官方包包含全部主题文件,包括:
298+
// default.css 默认明亮主题
299+
// dark.css 默认暗黑主题
300+
// jmapp.css、jrkf.css 主题
301+
// 例如:jmapp 包只包含 jmapp 的主题文件,且是默认主题文件。
290302
files.forEach(filePath => {
291303
const themeName = basename(filePath, 'scss').replace('theme-', '')
292304
if (!projectID) {
@@ -331,16 +343,16 @@ async function copyStyles() {
331343
}
332344

333345
// 构建样式
334-
async function buildCSS(p) {
335-
const cssFiles = await glob(['src/packages/**/*.scss'], {
346+
async function buildCSS(themeName = '') {
347+
const componentScssFiles = await glob(['src/packages/**/*.scss'], {
336348
ignore: ['src/packages/**/demo.scss'],
337349
})
338350

339351
const variables = await readFile(
340-
join(__dirname, '../src/styles/variables.scss'),
352+
join(__dirname, `../src/styles/variables${themeName ? `-${themeName}` : ''}.scss`),
341353
)
342-
for (const file of cssFiles) {
343-
const button = await readFile(join(__dirname, '../', file), {
354+
for (const file of componentScssFiles) {
355+
const scssContent = await readFile(join(__dirname, '../', file), {
344356
encoding: 'utf8',
345357
})
346358
// countup 是特例
@@ -350,30 +362,11 @@ async function buildCSS(p) {
350362
'../src/packages',
351363
base.replace('.scss', ''),
352364
)
353-
const code = sass.compileString(variables + '\n' + button, {
354-
loadPaths: [loadPath],
355-
})
356365
const cssPath = relative('src', loadPath)
357-
// 写 css 文件
358-
await dest(join(`${dist}/es`, cssPath, 'style/style.css'), code.css)
359-
await dest(join(`${dist}/es`, cssPath, 'style/css.js'), `import './style.css'`)
360-
361-
await dest(join(`${dist}/cjs`, cssPath, 'style/style.css'), code.css)
362-
await dest(
363-
join(`${dist}/cjs`, cssPath, 'style/css.js'),
364-
`import './style.css'`,
365-
)
366-
367-
// copy harmonycss
368-
if (file.indexOf('countup') === -1) {
369-
await copy(join(__dirname, '../', file.replace('scss', 'harmony.css')), join(`${dist}/cjs`, cssPath, 'style/style.harmony.css'))
370-
await copy(join(__dirname, '../', file.replace('scss', 'harmony.css')), join(`${dist}/es`, cssPath, 'style/style.harmony.css'))
371-
}
372-
373366
// 删除 import
374367
// 写入 style.scss
375368
const atRules = []
376-
await postcss([
369+
const postcssRes = await postcss([
377370
{
378371
postcssPlugin: 'remove-atrule',
379372
AtRule(root) {
@@ -391,13 +384,22 @@ async function buildCSS(p) {
391384
},
392385
},
393386
])
394-
.process(button, { from: loadPath, syntax: scss })
387+
.process(scssContent, { from: loadPath, syntax: scss })
395388
.then((result) => {
396-
dest(join(`${dist}/es`, cssPath, `style/${base}`), result.css)
397-
dest(join(`${dist}/cjs`, cssPath, `style/${base}`), result.css)
389+
return result
398390
})
391+
const themeDir = themeName ? `style-${themeName}` : 'style'
392+
await dest(join(`${dist}/es`, cssPath, `${themeDir}/${base}`), postcssRes.css)
393+
await dest(join(`${dist}/cjs`, cssPath, `${themeDir}/${base}`), postcssRes.css)
394+
395+
const code = sass.compileString(variables + '\n' + postcssRes.css.replaceAll('../../../../', '../../'), {
396+
loadPaths: [loadPath],
397+
})
398+
await dest(join(`${dist}/es`, cssPath, `${themeDir}/style.css`), code.css)
399+
await dest(join(`${dist}/cjs`, cssPath, `${themeDir}/style.css`), code.css)
399400

400401
const jsContent = []
402+
const cssContent = []
401403
atRules.forEach((rule) => {
402404
rule = rule.replaceAll('\'', '')
403405
if (rule.indexOf('../styles/') > -1) {
@@ -407,18 +409,33 @@ async function buildCSS(p) {
407409
const base = basename(rule)
408410
const ext = extname(base)
409411
const name = base.replace(ext, '')
410-
jsContent.push(`import '../../${name}/style';`)
412+
jsContent.push(`import '../../${name}/${themeDir}';`)
413+
cssContent.push(`import '../../${name}/${themeDir}/css';`)
411414
}
412415
})
413416
jsContent.push(`import './${base}';`)
417+
cssContent.push(`import './style.css';`)
414418

415419
await dest(
416-
join(`${dist}/cjs`, cssPath, `style/index.js`),
420+
join(`${dist}/cjs`, cssPath, `${themeDir}/index.js`),
417421
jsContent.join('\n'),
418422
)
419-
await dest(join(`${dist}/es`, cssPath, `style/index.js`), jsContent.join('\n'))
420-
}
423+
await dest(join(`${dist}/es`, cssPath, `${themeDir}/index.js`), jsContent.join('\n'))
424+
425+
// 写 css 文件
426+
await dest(join(`${dist}/es`, cssPath, `${themeDir}/css.js`), cssContent.join('\n'))
427+
await dest(
428+
join(`${dist}/cjs`, cssPath, `${themeDir}/css.js`),
429+
cssContent.join('\n'),
430+
)
421431

432+
// copy harmonycss
433+
if (file.indexOf('countup') === -1) {
434+
const harmonyCss = join(__dirname, '../', file.replace('scss', 'harmony.css'))
435+
await copy(harmonyCss, join(`${dist}/cjs`, cssPath, 'style/style.harmony.css'))
436+
await copy(harmonyCss, join(`${dist}/es`, cssPath, 'style/style.harmony.css'))
437+
}
438+
}
422439
}
423440

424441
function generateReleasePackageJson() {
@@ -474,18 +491,36 @@ console.time('build UMD')
474491
await buildUMD()
475492
console.timeEnd('build UMD')
476493

477-
console.time('Build CSS')
478-
await buildCSS()
479-
console.timeEnd('Build CSS')
480494

481495
console.time('Copy Styles')
482496
await copyStyles()
483497
console.timeEnd('Copy Styles')
484498

499+
console.time('Build CSS')
500+
await buildCSS()
501+
console.timeEnd('Build CSS')
502+
503+
console.time('Build jmapp CSS')
504+
await buildCSS('jmapp')
505+
console.timeEnd('Build jmapp CSS')
506+
507+
console.time('Build jrkf CSS')
508+
await buildCSS('jrkf')
509+
console.timeEnd('Build jrkf CSS')
510+
485511
console.time('Build All CSS')
486512
await buildAllCSS()
487513
console.timeEnd('Build All CSS')
488514

515+
console.time('Build All jrkf CSS')
516+
await buildAllCSS('jrkf')
517+
console.timeEnd('Build All jrkf CSS')
518+
519+
console.time('Build All jmapp CSS')
520+
await buildAllCSS('jmapp')
521+
console.timeEnd('Build All jmapp CSS')
522+
523+
489524
console.time('Build Theme CSS')
490525
await buildThemeCSS()
491526
console.timeEnd('Build Theme CSS')

0 commit comments

Comments
 (0)