Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor code, drop more legacy stuff #158

Merged
merged 11 commits into from
Jan 16, 2021
92 changes: 46 additions & 46 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,12 @@ Webpack's [`resolve.mainFields`](https://webpack.js.org/configuration/resolve/#r

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.

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.
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://github.com/webpack-contrib/mini-css-extract-plugin) to the mix to output the css to a separate file.

```javascript
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const mode = process.env.NODE_ENV || 'development';
const prod = mode === 'production';
...
module: {
rules: [
Expand All @@ -80,23 +83,49 @@ A better option is to extract the CSS into a separate file. Using the `emitCss`
},
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: 'css-loader',
}),
use: [
prod ? MiniCssExtractPlugin.loader :'style-loader',
{
loader: 'css-loader',
options: {
url: false, //necessary if you use url('/path/to/some/asset.png|jpg|gif')
}
}
]
},
...
]
},
...
plugins: [
new ExtractTextPlugin('styles.css'),
new MiniCssExtractPlugin('styles.css'),
...
]
...
```

Alternatively, if you're handling styles in some other way and just want to prevent the CSS being added to your JavaScript bundle, use `css: false`.
Note that the configuration shown above switches off `MiniCssExtractPlugin` in development mode in favour of using CSS javascript injection. This is recommended by `MiniCssExtractPlugin` because it does not support hot reloading.

`prod` indicates, that `NODE_ENV=production` has been set from `package.json` or manually (`NODE_ENV=production npx webpack`) for production builds. We can rely on that to make dynamic adjustments to the config.

Additionally, if you're using multiple entrypoints, you may wish to change `new MiniCssExtractPlugin('styles.css')` for `new MiniCssExtractPlugin('[name].css')` to generate one CSS file per entrypoint.

Warning: in production, if you have set `sideEffects: false` in your `package.json`, `MiniCssExtractPlugin` has a tendency to drop CSS, regardless of whether it's included in your svelte components.

Alternatively, if you're handling styles in some other way and just want to prevent the CSS being added to your JavaScript bundle, use

```javascript
...
use: {
loader: 'svelte-loader',
options: {
compilerOptions: {
css: false
}
},
},
...
```

### Source maps

Expand All @@ -112,29 +141,24 @@ module.exports = {
module: {
rules: [
...
{
test: /\.(html|svelte)$/,
exclude: /node_modules/,
use: {
loader: 'svelte-loader',
options: {
emitCss: true,
},
},
},
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: [{ loader: 'css-loader', options: { sourceMap: true } }],
}),
use: [
prod ? MiniCssExtractPlugin.loader :'style-loader',
{
loader: 'css-loader',
options: {
sourceMap: true
}
}
]
},
...
]
},
...
plugins: [
new ExtractTextPlugin('styles.css'),
new MiniCssExtractPlugin('styles.css'),
...
]
...
Expand Down Expand Up @@ -231,30 +255,6 @@ module.exports = {
}
```

#### External Dependencies
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why was this section removed?

Copy link
Contributor Author

@non25 non25 Jan 16, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because externalDependencies option was removed ?
or this option is purely for webpack ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, right you are 😄


If you rely on any external dependencies (files required in a preprocessor for example) you might want to watch these files for changes and re-run svelte compile.

Webpack allows [loader dependencies](https://webpack.js.org/contribute/writing-a-loader/#loader-dependencies) to trigger a recompile. svelte-loader exposes this API via `options.externalDependencies`.
For example:

```js
...
const variables = path.resolve('./variables.js');
...
{
test: /\.(html|svelte)$/,
use: [
{
loader: 'svelte-loader',
options: {
externalDependencies: [variables]
}
}
]
}
```

## License

MIT
38 changes: 4 additions & 34 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,43 +7,13 @@ function posixify(file) {
return file.replace(/[/\\]/g, '/');
}

function normalize(compiled) {
// svelte.compile signature changed in 1.60 — this avoids
// future deprecation warnings while preserving backwards
// compatibility
const js = compiled.js || { code: compiled.code, map: compiled.map };

const css = compiled.css && typeof compiled.css === 'object'
? compiled.css
: { code: compiled.css, map: compiled.cssMap };

return { js, css, ast: compiled.ast, warnings: compiled.warnings || compiled.stats.warnings || [] };
}

const warned = {};
function deprecatePreprocessOptions(options) {
const preprocessOptions = {};

['markup', 'style', 'script'].forEach(kind => {
if (options[kind]) {
if (!warned[kind]) {
console.warn(`[svelte-loader] DEPRECATION: options.${kind} is now options.preprocess.${kind}`);
warned[kind] = true;
}
preprocessOptions[kind] = options[kind];
}
});

options.preprocess = options.preprocess || preprocessOptions;
}

const virtualModules = new Map();
let index = 0;

module.exports = function(source, map) {
this.cacheable();

const options = Object.assign({}, getOptions(this));
const options = { ...getOptions(this) };
const callback = this.async();

if (options.cssPath) {
Expand All @@ -65,7 +35,7 @@ module.exports = function(source, map) {

const handleWarning = warning => this.emitWarning(new Error(warning));

deprecatePreprocessOptions(options);
options.preprocess = options.preprocess || {};
options.preprocess.filename = compileOptions.filename;

preprocess(source, options.preprocess).then(processed => {
Expand All @@ -76,7 +46,7 @@ module.exports = function(source, map) {
}

const compiled = compile(processed.toString(), compileOptions);
let { js, css, warnings } = normalize(compiled);
let { js, css, warnings } = compiled;

warnings.forEach(
options.onwarn
Expand All @@ -85,7 +55,7 @@ module.exports = function(source, map) {
);

if (options.hotReload && !isProduction && !isServer) {
const hotOptions = Object.assign({}, options.hotOptions);
const hotOptions = { ...options.hotOptions };
const id = JSON.stringify(relative(process.cwd(), compileOptions.filename));
js.code = makeHot(id, js.code, hotOptions, compiled, source, compileOptions);
}
Expand Down
2 changes: 1 addition & 1 deletion lib/hot-api.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,5 +99,5 @@ export const applyHmr = makeApplyHmr(args => {
accept,
};

return Object.assign({}, args, { hot });
return { ...args, hot };
});
29 changes: 0 additions & 29 deletions test/loader.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -270,35 +270,6 @@ describe('loader', () => {
});
});

describe('deprecations', () => {
it('should warn on options.style', done => {
const { warn } = console;
const warnings = [];

console.warn = msg => {
warnings.push(msg);
};

testLoader(
'test/fixtures/style-valid.html',
(err, code, map) => {
expect(code).to.contain('50px');
expect(warnings).to.deep.equal([
'[svelte-loader] DEPRECATION: options.style is now options.preprocess.style'
]);
console.warn = warn;
},
{
style: ({ content }) => {
return {
code: content.replace(/\$size/gi, '50px')
};
}
}
)(done);
});
});

describe('hotReload', () => {
it(
'should configure hotReload=false (default)',
Expand Down