Skip to content

Commit d8637dd

Browse files
committed
Make it work with Webpack 5, use webpack-virtual-modules as a dependency
1 parent d4e2c20 commit d8637dd

File tree

5 files changed

+57
-201
lines changed

5 files changed

+57
-201
lines changed

README.md

+32-11
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,13 @@ Configure inside your `webpack.config.js`:
3333
test: /\.(html|svelte)$/,
3434
exclude: /node_modules/,
3535
use: 'svelte-loader'
36+
},
37+
{
38+
// required to prevent errors from Svelte on Webpack 5+
39+
test: /svelte\/.*\.mjs$/,
40+
resolve: {
41+
fullySpecified: false
42+
}
3643
}
3744
...
3845
]
@@ -54,9 +61,13 @@ Webpack's [`resolve.mainFields`](https://webpack.js.org/configuration/resolve/#r
5461

5562
If your Svelte components contain `<style>` tags, by default the compiler will add JavaScript that injects those styles into the page when the component is rendered. That's not ideal, because it adds weight to your JavaScript, prevents styles from being fetched in parallel with your code, and can even cause CSP violations.
5663

57-
A better option is to extract the CSS into a separate file. Using the `emitCss` option as shown below would cause a virtual CSS file to be emitted for each Svelte component. The resulting file is then imported by the component, thus following the standard Webpack compilation flow. Add [ExtractTextPlugin](https://github.com/webpack-contrib/extract-text-webpack-plugin) to the mix to output the css to a separate file.
64+
A better option is to extract the CSS into a separate file. Using the `emitCss` option as shown below would cause a virtual CSS file to be emitted for each Svelte component. The resulting file is then imported by the component, thus following the standard Webpack compilation flow. Add [MiniCssExtractPlugin](https://webpack.js.org/plugins/mini-css-extract-plugin/) to the mix to output the css to a separate file.
65+
66+
Make sure to add SveltePlugin like shown below, which allows emitting virtual CSS files. It is a wrapper around webpack-virtual-modules, connected to the svelte-loader.
5867

5968
```javascript
69+
const SveltePlugin = require('svelte-loader').plugin;
70+
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
6071
...
6172
module: {
6273
rules: [
@@ -73,17 +84,20 @@ A better option is to extract the CSS into a separate file. Using the `emitCss`
7384
},
7485
{
7586
test: /\.css$/,
76-
use: ExtractTextPlugin.extract({
77-
fallback: 'style-loader',
78-
use: 'css-loader',
79-
}),
87+
use: [
88+
MiniCssExtractPlugin.loader,
89+
'css-loader'
90+
]
8091
},
8192
...
8293
]
8394
},
8495
...
8596
plugins: [
86-
new ExtractTextPlugin('styles.css'),
97+
new MiniCssExtractPlugin({
98+
filename: '[name].css'
99+
}),
100+
new SveltePlugin(),
87101
...
88102
]
89103
...
@@ -115,19 +129,26 @@ module.exports = {
115129
},
116130
},
117131
},
132+
118133
{
119134
test: /\.css$/,
120-
use: ExtractTextPlugin.extract({
121-
fallback: 'style-loader',
122-
use: [{ loader: 'css-loader', options: { sourceMap: true } }],
123-
}),
135+
use: [
136+
MiniCssExtractPlugin.loader,
137+
{
138+
loader: 'css-loader',
139+
options: { sourceMap: true }
140+
}
141+
]
124142
},
125143
...
126144
]
127145
},
128146
...
129147
plugins: [
130-
new ExtractTextPlugin('styles.css'),
148+
new MiniCssExtractPlugin({
149+
filename: '[name].css'
150+
}),
151+
new SveltePlugin(),
131152
...
132153
]
133154
...

index.js

+22-10
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
const { basename, extname, relative } = require('path');
22
const { getOptions } = require('loader-utils');
3-
const VirtualModules = require('./lib/virtual');
3+
const VirtualModules = require('webpack-virtual-modules');
44

55
const hotApi = require.resolve('./lib/hot-api.js');
66

@@ -96,13 +96,9 @@ function deprecatePreprocessOptions(options) {
9696
options.preprocess = options.preprocess || preprocessOptions;
9797
}
9898

99-
const virtualModuleInstances = new Map();
100-
101-
module.exports = function(source, map) {
102-
if (this._compiler && !virtualModuleInstances.has(this._compiler)) {
103-
virtualModuleInstances.set(this._compiler, new VirtualModules(this._compiler));
104-
}
99+
let virtualModuleInstances = new WeakMap();
105100

101+
function loader(source, map) {
106102
const virtualModules = virtualModuleInstances.get(this._compiler);
107103

108104
this.cacheable();
@@ -169,9 +165,14 @@ module.exports = function(source, map) {
169165
css.code += '\n/*# sourceMappingURL=' + css.map.toUrl() + '*/';
170166
js.code = js.code + `\nimport '${posixify(cssFilepath)}';\n`;
171167

172-
if (virtualModules) {
173-
virtualModules.writeModule(cssFilepath, css.code);
168+
if(!virtualModules) {
169+
throw new Error(
170+
'You should add SveltePlugin to the plugins array of your ' +
171+
'webpack.config.js to be able to emit css'
172+
);
174173
}
174+
175+
virtualModules.writeModule(cssFilepath, css.code);
175176
}
176177

177178
callback(null, js.code, js.map);
@@ -180,4 +181,15 @@ module.exports = function(source, map) {
180181
// context when logging to console
181182
callback(new Error(`${err.name}: ${err.toString()}`));
182183
});
183-
};
184+
}
185+
186+
class SveltePlugin extends VirtualModules {
187+
apply(compiler) {
188+
virtualModuleInstances.set(compiler, this);
189+
super.apply(compiler);
190+
}
191+
}
192+
193+
loader.plugin = SveltePlugin;
194+
195+
module.exports = loader;

lib/virtual-stats.js

-89
This file was deleted.

lib/virtual.js

-89
This file was deleted.

package.json

+3-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
],
1717
"dependencies": {
1818
"loader-utils": "^1.1.0",
19-
"svelte-dev-helper": "^1.1.9"
19+
"svelte-dev-helper": "^1.1.9",
20+
"webpack-virtual-modules": "^0.4.1"
2021
},
2122
"devDependencies": {
2223
"chai": "^4.1.2",
@@ -25,7 +26,7 @@
2526
"mocha": "^5.2.0",
2627
"sinon": "^6.1.5",
2728
"sinon-chai": "^3.2.0",
28-
"svelte": "^3.0.0-beta.5"
29+
"svelte": "^3.0.0"
2930
},
3031
"peerDependencies": {
3132
"svelte": ">1.44.0"

0 commit comments

Comments
 (0)