Skip to content

Commit f26aa6d

Browse files
committed
feature #781 add svelte support to webpack encore (zairigimad, weaverryan)
This PR was merged into the main branch. Discussion ---------- add svelte support to webpack encore > Svelte is a radical new approach to building user interfaces. Whereas traditional frameworks like React and Vue do the bulk of their work in the browser, Svelte shifts that work into a compile step that happens when you build your app. [https://svelte.dev/](https://svelte.dev/) The goal of this PR is to add support of Svelte to Webpack Encore. - [ ] Update Documentation https://symfony.com/doc/current/frontend/encore/advanced-config.html#having-the-full-control-on-loaders-rules Commits ------- 9f6056b updating svelte and -loader versions 3799313 add functional test for svelte 21d7bea fix CI d28e57c add suggestion of package if not installed bc15bb8 fix lint f8d2dcc fix extension 5ff5b90 add svelte support to webpack encore
2 parents 1f741c9 + 9f6056b commit f26aa6d

10 files changed

+1004
-810
lines changed

fixtures/js/hello_world.svelte

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<script>
2+
let name = 'world';
3+
</script>
4+
5+
<h1>Hello {name}!</h1>

index.js

+13
Original file line numberDiff line numberDiff line change
@@ -1726,6 +1726,19 @@ class Encore {
17261726
runtimeConfig = null;
17271727
webpackConfig = null;
17281728
}
1729+
1730+
/**
1731+
* If enabled, the SvelteJs loader is enabled.
1732+
*
1733+
* https://github.com/sveltejs/svelte-loader
1734+
*
1735+
* @returns {Encore}
1736+
*/
1737+
enableSvelte() {
1738+
webpackConfig.enableSvelte();
1739+
1740+
return this;
1741+
}
17291742
}
17301743

17311744
/**

lib/WebpackConfig.js

+6
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ class WebpackConfig {
9595
this.useBabelTypeScriptPreset = false;
9696
this.useWebpackNotifier = false;
9797
this.useHandlebarsLoader = false;
98+
this.useSvelte = false;
9899

99100
// Features/Loaders options
100101
this.copyFilesConfigs = [];
@@ -150,6 +151,7 @@ class WebpackConfig {
150151
eslint: () => {},
151152
typescript: () => {},
152153
handlebars: () => {},
154+
svelte: () => {},
153155
};
154156

155157
// Plugins options
@@ -692,6 +694,10 @@ class WebpackConfig {
692694
}
693695
}
694696

697+
enableSvelte() {
698+
this.useSvelte = true;
699+
}
700+
695701
enableTypeScriptLoader(callback = () => {}) {
696702
if (this.useBabelTypeScriptPreset) {
697703
throw new Error('Encore.enableTypeScriptLoader() can not be called when Encore.enableBabelTypeScriptPreset() has been called.');

lib/config-generator.js

+12-1
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ class ConfigGenerator {
120120
config.stats = this.buildStatsConfig();
121121

122122
config.resolve = {
123-
extensions: ['.wasm', '.mjs', '.js', '.json', '.jsx', '.vue', '.ts', '.tsx'],
123+
extensions: ['.wasm', '.mjs', '.js', '.json', '.jsx', '.vue', '.ts', '.tsx', '.svelte'],
124124
alias: {}
125125
};
126126

@@ -403,6 +403,17 @@ class ConfigGenerator {
403403
}));
404404
}
405405

406+
if (this.webpackConfig.useSvelte) {
407+
rules.push(applyRuleConfigurationCallback('svelte', {
408+
resolve: {
409+
mainFields: ['svelte', 'browser', 'module', 'main'],
410+
extensions: ['.mjs', '.js', '.svelte'],
411+
},
412+
test: /\.svelte$/,
413+
loader: 'svelte-loader',
414+
}));
415+
}
416+
406417
if (this.webpackConfig.useVueLoader) {
407418
rules.push(applyRuleConfigurationCallback('vue', {
408419
test: /\.vue$/,

lib/features.js

+8
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,14 @@ const features = {
161161
{ name: '@symfony/stimulus-bridge', enforce_version: true }
162162
],
163163
description: 'enable Stimulus bridge'
164+
},
165+
svelte: {
166+
method: 'enableSvelte()',
167+
packages: [
168+
{ name: 'svelte', enforce_version: true },
169+
{ name: 'svelte-loader', enforce_version: true }
170+
],
171+
description: 'process Svelte JS files'
164172
}
165173
};
166174

package.json

+2
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@
9898
"webpack": "^5.72",
9999
"webpack-cli": "^4.9.1",
100100
"webpack-notifier": "^1.15.0",
101+
"svelte": "^3.50.0",
102+
"svelte-loader": "^3.1.0",
101103
"zombie": "^6.1.4"
102104
},
103105
"peerDependencies": {

test/WebpackConfig.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -1300,12 +1300,12 @@ describe('WebpackConfig object', () => {
13001300

13011301
expect(config.externals).to.deep.equals([]);
13021302

1303-
config.addExternals({ 'jquery': 'jQuery', 'react': 'react' });
1303+
config.addExternals({ 'jquery': 'jQuery', 'react': 'react', 'svelte': 'svelte' });
13041304
config.addExternals({ 'lodash': 'lodash' });
13051305
config.addExternals(/^(jquery|\$)$/i);
13061306

13071307
expect(config.externals).to.deep.equals([
1308-
{ 'jquery': 'jQuery', 'react': 'react' },
1308+
{ 'jquery': 'jQuery', 'react': 'react', 'svelte': 'svelte' },
13091309
{ 'lodash': 'lodash' },
13101310
/^(jquery|\$)$/i
13111311
]);
@@ -1494,7 +1494,7 @@ describe('WebpackConfig object', () => {
14941494

14951495
expect(() => {
14961496
config.configureLoaderRule('reason');
1497-
}).to.throw('Loader "reason" is not configurable. Valid loaders are "javascript", "css", "images", "fonts", "sass", "less", "stylus", "vue", "eslint", "typescript", "handlebars" and the aliases "js", "ts", "scss".');
1497+
}).to.throw('Loader "reason" is not configurable. Valid loaders are "javascript", "css", "images", "fonts", "sass", "less", "stylus", "vue", "eslint", "typescript", "handlebars", "svelte" and the aliases "js", "ts", "scss".');
14981498
});
14991499

15001500
it('Call method with not a valid callback', () => {

test/functional.js

+17
Original file line numberDiff line numberDiff line change
@@ -1309,6 +1309,23 @@ module.exports = {
13091309
});
13101310
});
13111311

1312+
it('When enabled, svelte is transformed', (done) => {
1313+
const config = createWebpackConfig('www/build', 'dev');
1314+
config.setPublicPath('/build');
1315+
config.addEntry('main', './js/hello_world.svelte');
1316+
config.enableSvelte();
1317+
1318+
testSetup.runWebpack(config, (webpackAssert) => {
1319+
// check that babel transformed the svelte files
1320+
webpackAssert.assertOutputFileContains(
1321+
'main.js',
1322+
'SvelteComponent'
1323+
);
1324+
1325+
done();
1326+
});
1327+
});
1328+
13121329
it('When enabled, preact JSX is transformed with preact-compat!', (done) => {
13131330
const config = createWebpackConfig('www/build', 'dev');
13141331
config.setPublicPath('/build');

test/index.js

+9
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,15 @@ describe('Public API', () => {
266266

267267
});
268268

269+
describe('enableSvelte', () => {
270+
271+
it('must return the API object', () => {
272+
const returnedValue = api.enableSvelte();
273+
expect(returnedValue).to.equal(api);
274+
});
275+
276+
});
277+
269278
describe('enablePreactPreset', () => {
270279

271280
it('must return the API object', () => {

0 commit comments

Comments
 (0)