Skip to content

Commit db92edc

Browse files
committed
Upgrade dependencies and fix build script hacks.
Special thanks to @stefanovualto for the workaround at #3
1 parent c99561d commit db92edc

File tree

3 files changed

+1167
-1173
lines changed

3 files changed

+1167
-1173
lines changed

package.json

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "svelte-custom-element",
33
"version": "0.1.0",
44
"description": "",
5-
"main": "src/index.svelte",
5+
"main": "dist/svelte-custom-element.js",
66
"scripts": {
77
"build": "node ./scripts/build.js",
88
"lint": "eslint --ext .js --ext .svelte src/",
@@ -15,9 +15,9 @@
1515
"@babel/core": "^7.11.6",
1616
"@babel/plugin-transform-runtime": "^7.12.1",
1717
"@rollup/plugin-babel": "^5.2.1",
18-
"@rollup/plugin-commonjs": "^14.0.0",
18+
"@rollup/plugin-commonjs": "^17.0.0",
1919
"@rollup/plugin-json": "^4.1.0",
20-
"@rollup/plugin-node-resolve": "^8.4.0",
20+
"@rollup/plugin-node-resolve": "^11.1.0",
2121
"@rollup/plugin-replace": "^2.3.3",
2222
"@storybook/addon-actions": "^6.0.21",
2323
"@storybook/addon-essentials": "^6.0.21",
@@ -29,21 +29,22 @@
2929
"babel-loader": "^8.1.0",
3030
"eslint": "^7.11.0",
3131
"jest": "^26.6.0",
32-
"node-sass": "^4.14.1",
32+
"node-sass": "^5.0.0",
3333
"postcss": "^8.1.0",
34-
"postcss-load-config": "^2.1.2",
34+
"postcss-load-config": "^3.0.0",
3535
"prettier": "^2.1.2",
3636
"raw-loader": "^4.0.2",
3737
"rollup": "^2.3.4",
38+
"rollup-plugin-css-only": "^3.1.0",
3839
"rollup-plugin-livereload": "^2.0.0",
39-
"rollup-plugin-svelte": "^6.0.0",
40+
"rollup-plugin-svelte": "^7.1.0",
4041
"rollup-plugin-svg-import": "^1.5.1",
4142
"rollup-plugin-terser": "^7.0.0",
4243
"sass": "^1.26.11",
4344
"sass-loader": "^10.0.3",
4445
"shelljs": "^0.8.4",
4546
"svelte": "^3.26.0",
46-
"svelte-loader": "^2.13.6",
47+
"svelte-loader": "^3.0.0",
4748
"svelte-preprocess": "^4.5.1"
4849
},
4950
"dependencies": {

scripts/build.js

Lines changed: 99 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const { babel } = require('@rollup/plugin-babel')
44
const { nodeResolve } = require('@rollup/plugin-node-resolve')
55
const commonjs = require('@rollup/plugin-commonjs')
66
const json = require('@rollup/plugin-json')
7+
const css = require('rollup-plugin-css-only')
78
const replace = require('@rollup/plugin-replace')
89
const livereload = require('rollup-plugin-livereload')
910
const terser = require('rollup-plugin-terser').terser
@@ -19,99 +20,115 @@ const buildPath = 'dist'
1920
const entryPoint = `${appPath}/src/index.svelte`
2021
const entryPointRegexp = /index\.svelte$/
2122
const moduleName = packageJson.name
23+
// Replace special characters for allowing scoped packages like "@scope/package"
24+
const displayModuleName = moduleName.replace('@', '').replace('/', '-')
2225
const moduleVersion = packageJson.version
2326

27+
// Used for package.json "main" property
28+
const moduleFile = `${buildPath}/${displayModuleName}.js`
29+
30+
const bundleName = `${displayModuleName}.${moduleVersion}.js`
31+
2432
const outputOptions = {
2533
sourcemap: true,
2634
format: 'iife',
2735
name: 'App',
28-
file: `${buildPath}/${moduleName}.${moduleVersion}.js`,
36+
file: `${buildPath}/${bundleName}`,
2937
}
3038

31-
const commonRollupPlugins = [
32-
json(),
33-
34-
// If you have external dependencies installed from
35-
// npm, you'll most likely need these plugins. In
36-
// some cases you'll need additional configuration -
37-
// consult the documentation for details:
38-
// https://github.com/rollup/plugins/tree/master/packages/commonjs
39-
nodeResolve({
40-
browser: true,
41-
dedupe: ['svelte'],
42-
}),
43-
44-
commonjs(),
45-
46-
// transpile to ES2015+
47-
babel({
48-
extensions: ['.js', '.mjs', '.html', '.svelte'],
49-
babelHelpers: 'runtime',
50-
}),
51-
]
52-
53-
async function generateNestedCSS() {
54-
let cssChunk
55-
39+
async function buildWebComponent({ minify }) {
5640
// 1. Create a bundle
5741
const bundle = await rollup.rollup({
5842
input: entryPoint,
5943
plugins: [
6044
svelte({
61-
// all nested child elements are built as normal svelte components
62-
customElement: false,
45+
compilerOptions: {
46+
dev: false,
47+
48+
// all nested child elements are built as normal svelte components
49+
customElement: false,
50+
},
51+
emitCss: true,
6352
exclude: entryPointRegexp,
6453
preprocess: sveltePreprocess(),
65-
// Extract CSS into a variable
66-
css: css => (cssChunk = css.code),
6754
}),
6855
svelte({
69-
customElement: true,
56+
compilerOptions: {
57+
// enable run-time checks when not in production
58+
dev: !production,
59+
60+
// we're generating a -- Web Component -- from index.svelte
61+
customElement: true,
62+
},
63+
emitCss: false,
7064
include: entryPointRegexp,
7165
preprocess: sveltePreprocess(),
7266
}),
7367

74-
...commonRollupPlugins,
75-
],
76-
})
77-
78-
// 2. Generate output specific code in-memory
79-
// You can call this function multiple times on the same bundle object
80-
await bundle.generate(outputOptions)
68+
// HACK! Inject nested CSS into custom element shadow root
69+
css({
70+
output(nestedCSS, styleNodes, bundle) {
71+
const code = bundle[bundleName].code
72+
const escapedCssChunk = nestedCSS
73+
.replace(/\n/g, '')
74+
.replace(/[\\"']/g, '\\$&')
75+
.replace(/\u0000/g, '\\0')
76+
77+
const matches = code.match(
78+
minify
79+
? /.shadowRoot.innerHTML='<style>(.*)<\/style>'/
80+
: /.shadowRoot.innerHTML = "<style>(.*)<\/style>"/,
81+
)
82+
83+
if (matches && matches[1]) {
84+
const style = matches[1]
85+
bundle[bundleName].code = code.replace(
86+
style,
87+
`${style}${escapedCssChunk}`,
88+
)
89+
} else {
90+
throw new Error(
91+
"Couldn't shadowRoot <style> tag for injecting styles",
92+
)
93+
}
94+
},
95+
}),
8196

82-
// 3. Escape css chunk characters.
83-
// For embedding the chunk into the main custom element
84-
const escapedCssChunk = cssChunk
85-
.replace(/\n/g, '')
86-
.replace(/[\\"']/g, '\\$&')
87-
.replace(/\u0000/g, '\\0')
97+
// HACK! Fix svelte/transitions in web components
8898

89-
return escapedCssChunk
90-
}
99+
// Use shadow root instead of document for transition style injecting
100+
replace({
101+
'.ownerDocument': '.getRootNode()',
102+
delimiters: ['', ''],
103+
}),
91104

92-
async function buildWebComponent({ nestedCSS, minify }) {
93-
// 1. Create a bundle
94-
const bundle = await rollup.rollup({
95-
input: entryPoint,
96-
plugins: [
97-
replace({ 'module-name': moduleName }),
98-
svelte({
99-
dev: false,
100-
// all nested child elements are built as normal svelte components
101-
customElement: false,
102-
exclude: entryPointRegexp,
103-
preprocess: sveltePreprocess(),
105+
// Append styles to shadow root
106+
replace({
107+
'.head.appendChild': '.appendChild',
108+
delimiters: ['', ''],
104109
}),
105-
svelte({
106-
// enable run-time checks when not in production
107-
dev: !production,
108-
// we're generating a -- Web Component -- from index.svelte
109-
customElement: true,
110-
include: entryPointRegexp,
111-
preprocess: sveltePreprocess(),
110+
111+
// END HACK
112+
113+
json(),
114+
115+
// If you have external dependencies installed from
116+
// npm, you'll most likely need these plugins. In
117+
// some cases you'll need additional configuration -
118+
// consult the documentation for details:
119+
// https://github.com/rollup/plugins/tree/master/packages/commonjs
120+
nodeResolve({
121+
browser: true,
122+
dedupe: ['svelte'],
112123
}),
113124

114-
...commonRollupPlugins,
125+
commonjs(),
126+
127+
// transpile to ES2015+
128+
babel({
129+
extensions: ['.js', '.mjs', '.html', '.svelte'],
130+
babelHelpers: 'runtime',
131+
}),
115132

116133
// Watch the `public` directory and refresh the
117134
// browser on changes when not in production
@@ -128,39 +145,20 @@ async function buildWebComponent({ nestedCSS, minify }) {
128145
const { output } = await bundle.generate(outputOptions)
129146
const { code, map } = output[0]
130147

131-
// 3. Inject CSS chunk into custom element shadow root
132-
const matches = code.match(
133-
minify
134-
? /.shadowRoot.innerHTML='<style>(.*)<\/style>'/
135-
: /_this.shadowRoot.innerHTML = \"<style>(.*)<\/style>\"/,
136-
)
137-
138-
let updatedCode = code
139-
140-
if (matches && matches[1]) {
141-
const style = matches[1]
142-
updatedCode = code.replace(style, `${style}${nestedCSS}`)
143-
}
144-
145-
// 4. HACK! Fix svelte/transitions in web components
146-
updatedCode = updatedCode
147-
// Use shadow root instead of document for transition style injecting
148-
.replace(/\.ownerDocument/, '.getRootNode()')
149-
// Append styles to shadow root
150-
.replace(/\.head\.appendChild/, '.appendChild')
151-
152-
// 5. Write bundles into files
148+
// 3. Write bundles into files
153149
const fileName = minify
154150
? `${outputOptions.file.replace('.js', '.min.js')}`
155151
: outputOptions.file
156152

157-
fs.writeFile(fileName, updatedCode, err => {
153+
// Normal bundle
154+
fs.writeFile(fileName, code, err => {
158155
if (err) {
159156
console.error(err)
160157
process.exit(1)
161158
}
162159
})
163160

161+
// Only create .map.js when code is minified
164162
if (minify) {
165163
fs.writeFile(fileName.replace('.js', '.js.map'), map.toString(), err => {
166164
if (err) {
@@ -169,19 +167,27 @@ async function buildWebComponent({ nestedCSS, minify }) {
169167
}
170168
})
171169
}
170+
171+
// Generic bundle for using as module entry point
172+
if (!minify) {
173+
fs.writeFile(moduleFile, code, err => {
174+
if (err) {
175+
console.error(err)
176+
process.exit(1)
177+
}
178+
})
179+
}
172180
}
173181

174182
async function main() {
175183
try {
176184
shell.mkdir('-p', buildPath)
177185

178-
const nestedCSS = await generateNestedCSS()
179-
180186
// builds readable bundle of the web component
181-
await buildWebComponent({ nestedCSS, minify: false })
187+
await buildWebComponent({ minify: false })
182188

183189
// builds minified bundle with sourcemap
184-
await buildWebComponent({ nestedCSS, minify: true })
190+
await buildWebComponent({ minify: true })
185191
} catch (ex) {
186192
console.error(ex)
187193
process.exit(1)

0 commit comments

Comments
 (0)