Skip to content

Commit 3efe73b

Browse files
committed
feat: add CSS file reference for styled share module
1 parent 493834d commit 3efe73b

File tree

9 files changed

+138
-64
lines changed

9 files changed

+138
-64
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { expect, test } from 'vitest'
2+
import path from 'node:path'
3+
import fs from 'node:fs'
4+
5+
function readFileWithRegexPattern(dirPath, regexPattern) {
6+
// Get all files in the directory
7+
const files = fs.readdirSync(dirPath);
8+
9+
// Find the file that matches the regex pattern
10+
const matchedFile = files.find(file => regexPattern.test(file));
11+
12+
if (!matchedFile) {
13+
throw new Error(`No file found matching pattern: ${regexPattern}`);
14+
}
15+
16+
// Read and return the file content
17+
return fs.readFileSync(path.join(dirPath, matchedFile), 'utf-8');
18+
}
19+
20+
test('should have css imported', () => {
21+
const dirPath = path.resolve(__dirname, '../host/dist/assets');
22+
const regexPattern = /^__federation_shared_shared-styled-.*\.js$/;
23+
try {
24+
const css = readFileWithRegexPattern(dirPath, regexPattern)
25+
expect(css).toMatch(/import.+\.css';/)
26+
} catch (error) {
27+
console.error(error)
28+
}
29+
})
30+

packages/examples/vue3-demo-esm-shared-store/host/package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
},
1111
"dependencies": {
1212
"vue": "^3.2.45",
13-
"pinia": "^2.0.21"
13+
"pinia": "^2.0.21",
14+
"shared-styled": "file:./shared-styled"
1415
},
1516
"devDependencies": {
1617
"@vitejs/plugin-vue": "^4.0.0",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import './style.css'
2+
3+
export {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"name": "shared-styled",
3+
"version": "1.0.0",
4+
"main": "index.js"
5+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.foo {
2+
color: red;
3+
}

packages/examples/vue3-demo-esm-shared-store/host/src/main.js

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { createApp} from "vue";
22
import { createPinia } from 'pinia'
3+
import 'shared-styled'
34
import App from "./App.vue";
45

56
const app = createApp(App);

packages/examples/vue3-demo-esm-shared-store/host/vite.config.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ export default defineConfig({
3434
myStore: {
3535
packagePath: './src/store.js',
3636
modulePreload: true,
37-
}
37+
},
38+
'shared-styled': {}
3839
}
3940
})
4041
],

packages/lib/src/prod/shared-production.ts

+37-2
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,14 @@
1313
// SPDX-License-Identifier: MulanPSL-2.0
1414
// *****************************************************************************
1515

16+
import MagicString from 'magic-string'
1617
import type { PluginHooks } from '../../types/pluginHooks'
1718
import { NAME_CHAR_REG, parseSharedOptions, removeNonRegLetter } from '../utils'
18-
import { parsedOptions } from '../public'
19+
import { parsedOptions, builderInfo } from '../public'
1920
import type { ConfigTypeSet, VitePluginFederationOptions } from 'types'
20-
import { basename, join, resolve } from 'path'
21+
import type { RenderedChunk } from 'rollup'
22+
import type { ChunkMetadata } from 'vite'
23+
import { basename, join, resolve, relative, dirname } from 'path'
2124
import { readdirSync, readFileSync, statSync } from 'fs'
2225
const sharedFilePathReg = /__federation_shared_(.+)-.{8}\.js$/
2326
import federation_fn_import from './federation_fn_import.js?raw'
@@ -151,6 +154,38 @@ export function prodSharedPlugin(
151154
}
152155
},
153156

157+
renderChunk(this, code, _chunk) {
158+
if (builderInfo.isShared) {
159+
const chunk = _chunk as RenderedChunk & { viteMetadata?: ChunkMetadata }
160+
const regRst = sharedFilePathReg.exec(chunk.fileName)
161+
if (
162+
regRst &&
163+
shareName2Prop.get(removeNonRegLetter(regRst[1], NAME_CHAR_REG))
164+
?.generate !== false &&
165+
chunk.type === 'chunk' &&
166+
chunk.viteMetadata?.importedCss.size
167+
) {
168+
/**
169+
* Inject the referenced style files at the top of the chunk.
170+
*/
171+
const magicString = new MagicString(code)
172+
for (const cssFileName of chunk.viteMetadata.importedCss) {
173+
let cssFilePath = relative(dirname(chunk.fileName), cssFileName)
174+
cssFilePath = cssFilePath.startsWith('.')
175+
? cssFilePath
176+
: `./${cssFilePath}`
177+
178+
magicString.prepend(`import '${cssFilePath}';`)
179+
}
180+
181+
return {
182+
code: magicString.toString(),
183+
map: magicString.generateMap({ hires: true })
184+
}
185+
}
186+
}
187+
},
188+
154189
outputOptions: function (outputOption) {
155190
// remove rollup generated empty imports,like import './filename.js'
156191
outputOption.hoistTransitiveImports = false

0 commit comments

Comments
 (0)