Skip to content

Commit

Permalink
Switch to vue-style-loader when using mix.vue()
Browse files Browse the repository at this point in the history
  • Loading branch information
thecrypticace committed Mar 14, 2021
1 parent 9780e7e commit 56eac79
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 3 deletions.
9 changes: 7 additions & 2 deletions src/components/CssWebpackConfig.js
Expand Up @@ -171,8 +171,9 @@ class CssWebpackConfig extends AutomaticComponent {
*
* @param {object} [options]
* @param {"auto" | "inline" | "extract"} options.method The method to use when handling CSS.
* @param {"default" | "per-file"} options.location Where these loaders are applied. The `default` set or on a per-file basis (used by preprocessors).
*/
static afterLoaders({ method = 'auto' } = {}) {
static afterLoaders({ method = 'auto', location = 'default' } = {}) {
const loaders = [];

if (method === 'auto') {
Expand All @@ -185,7 +186,11 @@ class CssWebpackConfig extends AutomaticComponent {
}

if (method === 'inline') {
loaders.push({ loader: 'style-loader' });
if (Mix.components.get('vue') && location === 'default') {
loaders.push({ loader: 'vue-style-loader' });
} else {
loaders.push({ loader: 'style-loader' });
}
} else if (method === 'extract') {
loaders.push({
loader: MiniCssExtractPlugin.loader,
Expand Down
2 changes: 1 addition & 1 deletion src/components/Preprocessor.js
Expand Up @@ -53,7 +53,7 @@ class Preprocessor {
let processUrls = this.shouldProcessUrls(preprocessor);

let loaders = [
...CssWebpackConfig.afterLoaders({ method: 'extract' }),
...CssWebpackConfig.afterLoaders({ method: 'extract', location: 'per-file' }),
{
loader: 'css-loader',
options: {
Expand Down
26 changes: 26 additions & 0 deletions test/features/vue.js
Expand Up @@ -38,6 +38,32 @@ test('it knows the Vue 2 compiler name', t => {
t.true(dependencies.includes('vue-template-compiler'));
});

test('it switches to vue-style-loader when not extracting styles', async t => {
mix.vue({ version: 2, extractStyles: false });

const config = await webpack.buildConfig();

assert.hasWebpackLoader(t, config, 'vue-style-loader');
assert.doesNotHaveWebpackLoader(t, config, 'style-loader');
assert.doesNotHaveWebpackLoader(t, config, /mini-css-extract-plugin/);
});

test('it does not switch to vue-style-loader when extracting styles', async t => {
mix.vue({ version: 2, extractStyles: true });

const config = await webpack.buildConfig();

assert.doesNotHaveWebpackLoader(t, config, 'vue-style-loader');
assert.hasWebpackLoader(t, config, /mini-css-extract-plugin/);
});

test('it does not use vue-style-loader when not using .vue', async t => {
const config = await webpack.buildConfig();

assert.doesNotHaveWebpackLoader(t, config, 'vue-style-loader');
assert.hasWebpackLoader(t, config, 'style-loader');
});

test('it appends vue styles to your sass compiled file', async t => {
mix.vue({ version: 2, extractStyles: true });
mix.js(`test/fixtures/app/src/vue/app-with-vue-and-scss.js`, 'js/app.js').sass(
Expand Down
28 changes: 28 additions & 0 deletions test/features/vue3.js
Expand Up @@ -34,6 +34,34 @@ test('it knows the Vue 3 compiler name', t => {
t.true(dependencies.includes('@vue/compiler-sfc'));
});

test('it switches to vue-style-loader when not extracting styles', async t => {
mix.vue({ version: 3, extractStyles: false });

const config = await webpack.buildConfig();

assert.hasWebpackLoader(t, config, 'vue-style-loader');
assert.doesNotHaveWebpackLoader(t, config, 'style-loader');
assert.doesNotHaveWebpackLoader(t, config, loader =>
loader.includes('mini-css-extract-plugin')
);
});

test('it does not switch to vue-style-loader when extracting styles', async t => {
mix.vue({ version: 3, extractStyles: true });

const config = await webpack.buildConfig();

assert.doesNotHaveWebpackLoader(t, config, 'vue-style-loader');
assert.hasWebpackLoader(t, config, /mini-css-extract-plugin/);
});

test('it does not use vue-style-loader when not using .vue', async t => {
const config = await webpack.buildConfig();

assert.doesNotHaveWebpackLoader(t, config, 'vue-style-loader');
assert.hasWebpackLoader(t, config, 'style-loader');
});

test('it appends vue styles to your sass compiled file', async t => {
mix.vue({ version: 3, extractStyles: true });

Expand Down
67 changes: 67 additions & 0 deletions test/helpers/assertions.js
@@ -1,6 +1,73 @@
import File from '../../src/File';

/**
* Check that a matching webpack rule can be found
*
* @param {import("ava").Assertions} t
* @param {import("webpack").Configuration} config
* @param {(rule: import("webpack").RuleSetRule) => boolean} test
*/
function hasWebpackRule(config, test) {
/** @param {import("webpack").RuleSetRule} rule */
const checkRule = rule =>
test(rule) ||
(rule.oneOf || []).find(checkRule) ||
(rule.rules || []).find(checkRule);

return !!config.module.rules.find(checkRule);
}

/**
* Check that a matching rule with the given loader can be found
*
* @param {import("webpack").Configuration} config
* @param {string|RegExp|((loader: string) => boolean)} loader
*/
function hasWebpackLoader(config, loader) {
const checkLoader =
typeof loader === 'string'
? str => str === loader
: loader instanceof RegExp
? str => loader.test(str)
: loader;

return hasWebpackRule(
config,
rule =>
(rule.loader && checkLoader(rule.loader)) ||
(rule.use || []).find(use => checkLoader(use.loader))
);
}

export default {
/**
* Assert that a matching webpack rule can be found
*
* @param {import("ava").Assertions} t
* @param {import("webpack").Configuration} config
* @param {(rule: import("webpack").RuleSetRule) => boolean} test
*/
hasWebpackRule: (t, config, test) => t.true(hasWebpackRule(config, test)),

/**
* Assert that a rule with the given loader can be found
*
* @param {import("ava").Assertions} t
* @param {import("webpack").Configuration} config
* @param {string|RegExp|((loader: string) => boolean)} loader
*/
hasWebpackLoader: (t, config, loader) => t.true(hasWebpackLoader(config, loader)),

/**
* Assert that a rule with the given loader cannot be found
*
* @param {import("ava").Assertions} t
* @param {import("webpack").Configuration} config
* @param {string|RegExp|((loader: string) => boolean)} loader
*/
doesNotHaveWebpackLoader: (t, config, loader) =>
t.false(hasWebpackLoader(config, loader)),

manifestEquals: (expected, t) => {
let manifest = JSON.parse(
File.find(`test/fixtures/app/dist/mix-manifest.json`).read()
Expand Down

0 comments on commit 56eac79

Please sign in to comment.