@@ -5,40 +5,188 @@ import { nodeResolve } from '@rollup/plugin-node-resolve'
55import replace from '@rollup/plugin-replace'
66import ts from '@rollup/plugin-typescript'
77import { recursiveMerge } from '@tarojs/helper'
8+ import fs from 'fs'
89import path from 'path'
910import { defineConfig } from 'rollup'
1011import externals from 'rollup-plugin-node-externals'
1112import postcss from 'rollup-plugin-postcss'
1213
13- function getPlugins ( pre = [ ] , post = [ ] ) {
14- return [
14+ // 合并 SCSS 文件到 original 构建输出目录
15+ function mergeScssFiles ( ) {
16+ return {
17+ name : 'merge-scss-files' ,
18+ writeBundle ( options ) {
19+ if ( ! options . dir ?. includes ( 'original' ) ) return
20+
21+ const outputDir = options . dir
22+ const srcDir = path . join ( process . cwd ( ) , 'src' )
23+ const componentsDir = path . join ( outputDir , 'components' )
24+
25+ if ( ! fs . existsSync ( componentsDir ) ) return
26+
27+ fs . readdirSync ( componentsDir ) . forEach ( ( component ) => {
28+ const componentDir = path . join ( componentsDir , component )
29+ if ( ! fs . statSync ( componentDir ) . isDirectory ( ) ) return
30+
31+ const styleDir = path . join ( componentDir , 'style' )
32+ fs . mkdirSync ( styleDir , { recursive : true } )
33+
34+ const srcStyleDir = path . join ( srcDir , 'components' , component , 'style' )
35+ const indexScssPath = path . join ( srcStyleDir , 'index.scss' )
36+
37+ if ( fs . existsSync ( indexScssPath ) ) {
38+ const mergedContent = mergeScssFile ( indexScssPath , srcStyleDir )
39+ fs . writeFileSync ( path . join ( styleDir , 'index.scss' ) , mergedContent )
40+ }
41+ } )
42+ } ,
43+ }
44+ }
45+
46+ // 递归合并 SCSS 文件内容
47+ function mergeScssFile ( filePath , baseDir , processedFiles = new Set ( ) ) {
48+ if ( processedFiles . has ( filePath ) ) return `/* Circular import: ${ path . basename ( filePath ) } */`
49+
50+ processedFiles . add ( filePath )
51+ let content = fs . readFileSync ( filePath , 'utf8' )
52+
53+ content = content . replace ( / @ i m p o r t \s + [ ' " ] ( [ ^ ' " ] + ) [ ' " ] ; ? / g, ( match , importPath ) => {
54+ let resolvedPath = importPath . startsWith ( './' )
55+ ? path . resolve ( path . dirname ( filePath ) , importPath )
56+ : path . resolve ( baseDir , importPath )
57+
58+ if ( ! resolvedPath . endsWith ( '.scss' ) ) resolvedPath += '.scss'
59+
60+ return fs . existsSync ( resolvedPath )
61+ ? `/* Imported from ${ importPath } */\n${ mergeScssFile ( resolvedPath , baseDir , processedFiles ) } `
62+ : `/* Missing: ${ importPath } */`
63+ } )
64+
65+ processedFiles . delete ( filePath )
66+ return content
67+ }
68+
69+ // 清理 original 构建中的样式文件
70+ function fixStyleImports ( ) {
71+ return {
72+ name : 'fix-style-imports' ,
73+ writeBundle ( options ) {
74+ if ( ! options . dir ?. includes ( 'original' ) ) return
75+
76+ const componentsDir = path . join ( options . dir , 'components' )
77+ if ( ! fs . existsSync ( componentsDir ) ) return
78+
79+ fs . readdirSync ( componentsDir ) . forEach ( ( component ) => {
80+ const componentDir = path . join ( componentsDir , component )
81+ if ( ! fs . statSync ( componentDir ) . isDirectory ( ) ) return
82+
83+ const indexJsPath = path . join ( componentDir , 'index.js' )
84+ if ( ! fs . existsSync ( indexJsPath ) ) return
85+
86+ // 确保样式 import 语句正确引用 SCSS 文件
87+ let content = fs . readFileSync ( indexJsPath , 'utf8' )
88+ // 将 .scss.js 或 .css.js 的导入改为 .scss 导入
89+ content = content . replace ( / i m p o r t \s + [ ' " ] \. \/ s t y l e \/ i n d e x \. ( s c s s | c s s ) \. j s [ ' " ] ; ? \s * / g, "import './style/index.scss';\n" )
90+ fs . writeFileSync ( indexJsPath , content )
91+
92+ // 清理 .scss.js 和 .scss.js.map 文件
93+ const styleDir = path . join ( componentDir , 'style' )
94+ if ( fs . existsSync ( styleDir ) ) {
95+ fs . readdirSync ( styleDir ) . forEach ( ( file ) => {
96+ if ( file . endsWith ( '.scss.js' ) || file . endsWith ( '.scss.js.map' ) ) {
97+ fs . unlinkSync ( path . join ( styleDir , file ) )
98+ }
99+ } )
100+ }
101+ } )
102+ } ,
103+ }
104+ }
105+
106+ // 自定义样式处理插件 - 替换 rollup-plugin-styles
107+ function customStylesPlugin ( ) {
108+ return {
109+ name : 'custom-styles-plugin' ,
110+ // 处理 SCSS 文件导入,让 Rollup 能够识别
111+ load ( id ) {
112+ if ( id . endsWith ( '.scss' ) ) {
113+ // 返回空的 CSS 内容,让 Rollup 能够处理导入
114+ return '/* SCSS file - processed by custom plugin */'
115+ }
116+ return null
117+ } ,
118+ // 在 writeBundle 阶段进行后处理
119+ writeBundle ( options ) {
120+ // 只处理 original 构建模式
121+ if ( ! options . dir ?. includes ( 'original' ) ) return
122+
123+ // 确保样式文件保持原始格式,不进行任何编译
124+ const outputDir = options . dir
125+ const componentsDir = path . join ( outputDir , 'components' )
126+
127+ if ( ! fs . existsSync ( componentsDir ) ) return
128+
129+ // 遍历所有组件目录,确保 SCSS 文件保持原始格式
130+ fs . readdirSync ( componentsDir ) . forEach ( ( component ) => {
131+ const componentDir = path . join ( componentsDir , component )
132+ if ( ! fs . statSync ( componentDir ) . isDirectory ( ) ) return
133+
134+ const styleDir = path . join ( componentDir , 'style' )
135+ if ( fs . existsSync ( styleDir ) ) {
136+ // 清理任何可能由其他插件生成的异常文件
137+ fs . readdirSync ( styleDir ) . forEach ( ( file ) => {
138+ const filePath = path . join ( styleDir , file )
139+ // 删除非 SCSS 的样式相关文件
140+ if ( file . endsWith ( '.css' ) ||
141+ file . endsWith ( '.css.map' ) ||
142+ file . endsWith ( '.scss.js' ) ||
143+ file . endsWith ( '.scss.js.map' ) ||
144+ file . endsWith ( '.css.js' ) ||
145+ file . endsWith ( '.css.js.map' ) ) {
146+ try {
147+ fs . unlinkSync ( filePath )
148+ } catch ( error ) {
149+ console . warn ( `Failed to delete file ${ filePath } :` , error . message )
150+ }
151+ }
152+ } )
153+ }
154+ } )
155+ }
156+ }
157+ }
158+
159+ function getPlugins ( pre = [ ] , post = [ ] , isOriginal = false ) {
160+ const basePlugins = [
15161 ...pre ,
16162 externals ( {
17163 deps : true ,
18164 devDeps : false ,
19165 } ) ,
20166 nodeResolve ( {
21167 preferBuiltins : false ,
22- mainFields : [ 'main:h5' , 'browser' , 'module' , 'jsnext:main' , 'main' ]
23- } ) ,
24- postcss ( {
25- extract : true ,
26- inject : { insertAt : 'top' } ,
27- minimize : true ,
168+ mainFields : [ 'main:h5' , 'browser' , 'module' , 'jsnext:main' , 'main' ] ,
28169 } ) ,
170+ // 根据模式选择样式处理插件
171+ isOriginal
172+ ? customStylesPlugin ( ) // 使用自定义样式插件,保持 SCSS 原始格式
173+ : postcss ( {
174+ extract : true ,
175+ inject : { insertAt : 'top' } ,
176+ minimize : true ,
177+ } ) ,
29178 ts ( ) ,
30179 commonjs ( {
31- include : '../../node_modules/**'
180+ include : '../../node_modules/**' ,
32181 } ) ,
33- ...post
182+ ...post ,
34183 ]
184+ return basePlugins
35185}
36186
37- function getAliasPlugin ( framework ) {
187+ function getAliasPlugin ( framework ) {
38188 return alias ( {
39- entries : [
40- { find : / .* h o o k s $ / , replacement : ( source ) => source . replace ( / h o o k s $ / , `hooks.${ framework } .ts` ) }
41- ]
189+ entries : [ { find : / .* h o o k s $ / , replacement : ( source ) => source . replace ( / h o o k s $ / , `hooks.${ framework } .ts` ) } ] ,
42190 } )
43191}
44192
@@ -52,7 +200,7 @@ const base = {
52200 preserveModules : true ,
53201 preserveModulesRoot : 'src' ,
54202 sourcemap : true ,
55- }
203+ } ,
56204}
57205
58206const babelConfig = {
@@ -63,93 +211,96 @@ const babelConfig = {
63211const react = ( ) => {
64212 const config = recursiveMerge ( { } , base , {
65213 input : {
66- index : 'src/index.react.ts'
214+ index : 'src/index.react.ts' ,
67215 } ,
68216 plugins : getPlugins (
69- [
70- getAliasPlugin ( 'react' ) ,
71- ] ,
217+ [ getAliasPlugin ( 'react' ) ] ,
72218 [
73219 babel ( {
74220 ...babelConfig ,
75221 presets : [
76- [ '@babel/preset-react' , {
77- pure : true ,
78- runtime : 'automatic' ,
79- useSpread : true ,
80- } ] ,
222+ [
223+ '@babel/preset-react' ,
224+ {
225+ pure : true ,
226+ runtime : 'automatic' ,
227+ useSpread : true ,
228+ } ,
229+ ] ,
81230 ] ,
82231 } ) ,
83232 replace ( {
84233 preventAssignment : true ,
85234 'process.env.FRAMEWORK' : JSON . stringify ( 'react' ) ,
86- } )
235+ } ) ,
87236 ]
88- )
237+ ) ,
89238 } )
90239 return config
91240}
92241
93242const solid = ( ) => {
94243 const config = recursiveMerge ( { } , base , {
95244 input : {
96- index : 'src/index.solid.ts'
245+ index : 'src/index.solid.ts' ,
97246 } ,
98247 output : {
99248 dir : 'dist/solid' ,
100249 } ,
101250 plugins : getPlugins (
102- [
103- getAliasPlugin ( 'solid' )
104- ] ,
251+ [ getAliasPlugin ( 'solid' ) ] ,
105252 [
106253 babel ( {
107254 ...babelConfig ,
108- presets : [
109- 'babel-preset-solid' ,
110- ] ,
255+ presets : [ 'babel-preset-solid' ] ,
111256 } ) ,
112257 replace ( {
113258 preventAssignment : true ,
114259 'process.env.FRAMEWORK' : JSON . stringify ( 'solid' ) ,
115260 } ) ,
116261 ]
117- )
262+ ) ,
118263 } )
119264 return config
120265}
121266
122- // 新增:样式产物配置
123- const styleBundles = ( ) => {
124- const inputs = {
125- picker : 'src/components/picker/style/index.scss' ,
126- }
127-
128- return Object . entries ( inputs ) . map ( ( [ name , inputPath ] ) => ( {
267+ const original = ( ) => {
268+ const config = recursiveMerge ( { } , base , {
129269 input : {
130- [ name ] : inputPath
270+ index : 'src/index.react.ts' ,
131271 } ,
132272 output : {
133- dir : 'dist/components' ,
134- entryFileNames : `${ name } /react-style/style.js` ,
135- format : 'es' ,
136- sourcemap : true ,
273+ dir : 'dist/original' ,
274+ // 移除 assetFileNames 配置,因为 original 构建不再生成 CSS 文件
137275 } ,
138- plugins : [
139- postcss ( {
140- extract : path . resolve ( `dist/components/${ name } /react-style/style.css` ) ,
141- minimize : true ,
142- sourceMap : true ,
143- modules : false ,
144- autoModules : false ,
145- } )
146- ]
147- } ) )
276+ plugins : getPlugins (
277+ [ getAliasPlugin ( 'react' ) ] ,
278+ [
279+ babel ( {
280+ ...babelConfig ,
281+ presets : [
282+ [
283+ '@babel/preset-react' ,
284+ {
285+ pure : true ,
286+ runtime : 'automatic' ,
287+ useSpread : true ,
288+ } ,
289+ ] ,
290+ ] ,
291+ } ) ,
292+ replace ( {
293+ preventAssignment : true ,
294+ 'process.env.FRAMEWORK' : JSON . stringify ( 'react' ) ,
295+ } ) ,
296+ mergeScssFiles ( ) , // 合并 SCSS 文件到输出目录
297+ fixStyleImports ( ) , // 修复样式 import 语句,保持 SCSS 引用
298+ ] ,
299+ true // 标记为 original 模式
300+ ) ,
301+ } )
302+ return config
148303}
149304
150305// 供 Loader 使用的运行时入口
151- export default defineConfig ( [
152- react ( ) ,
153- solid ( ) ,
154- ...styleBundles ( ) // 新增的样式产物
155- ] )
306+ export default defineConfig ( [ react ( ) , solid ( ) , original ( ) ] )
0 commit comments