mirror of
https://github.com/vuejs/vue-cli.git
synced 2026-02-12 18:08:35 -06:00
refactor + tests for CSS resolver
This commit is contained in:
@@ -1,3 +0,0 @@
|
||||
module.exports = {
|
||||
lintOnSave: false
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
module.exports = api => {}
|
||||
@@ -1,6 +1,6 @@
|
||||
jest.mock('fs')
|
||||
jest.mock('mock-config')
|
||||
jest.mock('vue-cli-plugin-foo')
|
||||
jest.mock('mock-config', () => ({ lintOnSave: false }), { virtual: true })
|
||||
jest.mock('vue-cli-plugin-foo', () => () => {}, { virtual: true })
|
||||
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
160
packages/@vue/cli-service/__tests__/css.spec.js
Normal file
160
packages/@vue/cli-service/__tests__/css.spec.js
Normal file
@@ -0,0 +1,160 @@
|
||||
const Service = require('../lib/Service')
|
||||
|
||||
const LANGS = ['css', 'sass', 'scss', 'less', 'styl', 'stylus']
|
||||
|
||||
const LOADERS = {
|
||||
css: 'css',
|
||||
sass: 'sass',
|
||||
scss: 'sass',
|
||||
less: 'less',
|
||||
styl: 'stylus',
|
||||
stylus: 'stylus'
|
||||
}
|
||||
|
||||
const genConfig = (pkg = {}, env) => {
|
||||
const prevEnv = process.env.NODE_ENV
|
||||
if (env) process.env.NODE_ENV = env
|
||||
const config = new Service('/', { pkg }).resolveWebpackConfig()
|
||||
process.env.NODE_ENV = prevEnv
|
||||
return config
|
||||
}
|
||||
|
||||
const findRule = (config, lang) => config.module.rules.find(rule => {
|
||||
const test = rule.test.toString().replace(/\\/g, '')
|
||||
return test.indexOf(`${lang}$`) > -1
|
||||
})
|
||||
|
||||
const findLoaders = (config, lang) => {
|
||||
const rule = findRule(config, lang)
|
||||
return rule.use.map(({ loader }) => loader.replace(/-loader$/, ''))
|
||||
}
|
||||
|
||||
const findOptions = (config, lang, _loader) => {
|
||||
const rule = findRule(config, lang)
|
||||
const use = rule.use.find(({ loader }) => `${_loader}-loader` === loader)
|
||||
return use.options
|
||||
}
|
||||
|
||||
const findUsesForVue = (config, lang) => {
|
||||
const vueOptions = findOptions(config, 'vue', 'vue')
|
||||
return vueOptions.loaders[lang]
|
||||
}
|
||||
|
||||
const findLoadersForVue = (config, lang) => {
|
||||
return findUsesForVue(config, lang).map(({ loader }) => loader.replace(/-loader$/, ''))
|
||||
}
|
||||
|
||||
const findOptionsForVue = (config, lang, _loader) => {
|
||||
const uses = findUsesForVue(config, lang)
|
||||
const use = uses.find(({ loader }) => `${_loader}-loader` === loader)
|
||||
return use.options
|
||||
}
|
||||
|
||||
const expectedCssLoaderModulesOptions = {
|
||||
importLoaders: 1,
|
||||
localIdentName: `[name]_[local]__[hash:base64:5]`,
|
||||
minimize: false,
|
||||
sourceMap: false,
|
||||
modules: true
|
||||
}
|
||||
|
||||
test('default loaders', () => {
|
||||
const config = genConfig()
|
||||
|
||||
LANGS.forEach(lang => {
|
||||
const loader = lang === 'css' ? [] : LOADERS[lang]
|
||||
expect(findLoaders(config, lang)).toEqual(['vue-style', 'css', 'postcss'].concat(loader))
|
||||
// vue-loader loaders should not include postcss because it's built-in
|
||||
expect(findLoadersForVue(config, lang)).toEqual(['vue-style', 'css'].concat(loader))
|
||||
// assert css-loader options
|
||||
expect(findOptions(config, lang, 'css')).toEqual({
|
||||
minimize: false,
|
||||
sourceMap: false
|
||||
})
|
||||
// files ending in .module.lang
|
||||
expect(findOptions(config, `module.${lang}`, 'css')).toEqual(expectedCssLoaderModulesOptions)
|
||||
})
|
||||
|
||||
// sass indented syntax
|
||||
expect(findOptions(config, 'sass', 'sass')).toEqual({ indentedSyntax: true, sourceMap: false })
|
||||
expect(findOptionsForVue(config, 'sass', 'sass')).toEqual({ indentedSyntax: true, sourceMap: false })
|
||||
})
|
||||
|
||||
test('production defaults', () => {
|
||||
const config = genConfig({}, 'production')
|
||||
const extractLoaderPath = require.resolve('extract-text-webpack-plugin/dist/loader')
|
||||
LANGS.forEach(lang => {
|
||||
const loader = lang === 'css' ? [] : LOADERS[lang]
|
||||
expect(findLoaders(config, lang)).toEqual([extractLoaderPath, 'vue-style', 'css', 'postcss'].concat(loader))
|
||||
expect(findLoadersForVue(config, lang)).toEqual([extractLoaderPath, 'vue-style', 'css'].concat(loader))
|
||||
expect(findOptions(config, lang, 'css')).toEqual({
|
||||
minimize: true,
|
||||
sourceMap: false
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
test('css.modules', () => {
|
||||
const config = genConfig({
|
||||
vue: {
|
||||
css: {
|
||||
modules: true
|
||||
}
|
||||
}
|
||||
})
|
||||
LANGS.forEach(lang => {
|
||||
expect(findOptions(config, lang, 'css')).toEqual(expectedCssLoaderModulesOptions)
|
||||
})
|
||||
})
|
||||
|
||||
test('css.extract', () => {
|
||||
const config = genConfig({
|
||||
vue: {
|
||||
css: {
|
||||
extract: false
|
||||
}
|
||||
}
|
||||
}, 'production')
|
||||
const extractLoaderPath = require.resolve('extract-text-webpack-plugin/dist/loader')
|
||||
LANGS.forEach(lang => {
|
||||
expect(findLoaders(config, lang)).not.toContain(extractLoaderPath)
|
||||
expect(findLoadersForVue(config, lang)).not.toContain(extractLoaderPath)
|
||||
})
|
||||
})
|
||||
|
||||
test('css.sourceMap', () => {
|
||||
const config = genConfig({
|
||||
vue: {
|
||||
css: {
|
||||
sourceMap: true
|
||||
}
|
||||
}
|
||||
})
|
||||
LANGS.forEach(lang => {
|
||||
expect(findOptions(config, lang, 'css').sourceMap).toBe(true)
|
||||
expect(findOptions(config, lang, 'postcss').sourceMap).toBe(true)
|
||||
expect(findOptions(config, lang, LOADERS[lang]).sourceMap).toBe(true)
|
||||
expect(findOptionsForVue(config, lang, 'css').sourceMap).toBe(true)
|
||||
expect(findOptionsForVue(config, lang, LOADERS[lang]).sourceMap).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
test('css.loaderOptions', () => {
|
||||
const data = '$env: production;'
|
||||
const config = genConfig({
|
||||
vue: {
|
||||
css: {
|
||||
loaderOptions: {
|
||||
sass: {
|
||||
data
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
expect(findOptions(config, 'scss', 'sass')).toEqual({ data, sourceMap: false })
|
||||
expect(findOptionsForVue(config, 'scss', 'sass')).toEqual({ data, sourceMap: false })
|
||||
expect(findOptions(config, 'sass', 'sass')).toEqual({ data, indentedSyntax: true, sourceMap: false })
|
||||
expect(findOptionsForVue(config, 'sass', 'sass')).toEqual({ data, indentedSyntax: true, sourceMap: false })
|
||||
})
|
||||
@@ -4,6 +4,7 @@ const debug = require('debug')
|
||||
const chalk = require('chalk')
|
||||
const readPkg = require('read-pkg')
|
||||
const merge = require('webpack-merge')
|
||||
const deepMerge = require('deepmerge')
|
||||
const Config = require('webpack-chain')
|
||||
const PluginAPI = require('./PluginAPI')
|
||||
const loadEnv = require('./util/loadEnv')
|
||||
@@ -12,7 +13,7 @@ const { warn, error } = require('@vue/cli-shared-utils')
|
||||
const { defaults, validate } = require('./options')
|
||||
|
||||
module.exports = class Service {
|
||||
constructor (context, { plugins, projectOptions, useBuiltIn } = {}) {
|
||||
constructor (context, { plugins, pkg, projectOptions, useBuiltIn } = {}) {
|
||||
process.VUE_CLI_SERVICE = this
|
||||
this.context = context
|
||||
this.webpackConfig = new Config()
|
||||
@@ -20,9 +21,9 @@ module.exports = class Service {
|
||||
this.webpackRawConfigFns = []
|
||||
this.devServerConfigFns = []
|
||||
this.commands = {}
|
||||
this.pkg = this.resolvePkg()
|
||||
this.projectOptions = Object.assign(
|
||||
defaults,
|
||||
this.pkg = this.resolvePkg(pkg)
|
||||
this.projectOptions = deepMerge(
|
||||
defaults(),
|
||||
this.loadProjectOptions(projectOptions)
|
||||
)
|
||||
|
||||
@@ -50,8 +51,10 @@ module.exports = class Service {
|
||||
}
|
||||
}
|
||||
|
||||
resolvePkg () {
|
||||
if (fs.existsSync(path.join(this.context, 'package.json'))) {
|
||||
resolvePkg (inlinePkg) {
|
||||
if (inlinePkg) {
|
||||
return inlinePkg
|
||||
} else if (fs.existsSync(path.join(this.context, 'package.json'))) {
|
||||
return readPkg.sync(this.context)
|
||||
} else {
|
||||
return {}
|
||||
|
||||
@@ -41,7 +41,7 @@ module.exports = (api, options) => {
|
||||
.test(/\.vue$/)
|
||||
.use('vue-loader')
|
||||
.loader('vue-loader')
|
||||
.options(Object.assign({}, options.vueLoaderOptions))
|
||||
.options(Object.assign({}, options.vueLoader))
|
||||
|
||||
webpackConfig.module
|
||||
.rule('images')
|
||||
|
||||
@@ -4,22 +4,23 @@ module.exports = (api, options) => {
|
||||
const ExtractTextPlugin = require('extract-text-webpack-plugin')
|
||||
|
||||
const isProd = process.env.NODE_ENV === 'production'
|
||||
const extract = isProd && options.extractCSS !== false
|
||||
const resolver = new CSSLoaderResolver({
|
||||
sourceMap: !!options.cssSourceMap,
|
||||
cssModules: !!options.cssModules,
|
||||
minimize: isProd,
|
||||
extract
|
||||
const userOptions = options.css || {}
|
||||
const extract = isProd && userOptions.extract !== false
|
||||
const baseOptions = Object.assign({}, userOptions, {
|
||||
extract,
|
||||
minimize: isProd
|
||||
})
|
||||
|
||||
const resolver = new CSSLoaderResolver(baseOptions)
|
||||
|
||||
// apply css loaders for vue-loader
|
||||
webpackConfig.module
|
||||
.rule('vue')
|
||||
.use('vue-loader')
|
||||
.tap(options => {
|
||||
// ensure user injected vueLoaderOptions take higher priority
|
||||
// ensure user injected vueLoader options take higher priority
|
||||
options.loaders = Object.assign(resolver.vue(), options.loaders)
|
||||
options.cssSourceMap = !!options.cssSourceMap
|
||||
options.cssSourceMap = !!userOptions.cssSourceMap
|
||||
return options
|
||||
})
|
||||
|
||||
@@ -46,12 +47,14 @@ module.exports = (api, options) => {
|
||||
}
|
||||
|
||||
// handle cssModules for *.module.js
|
||||
resolver.set('cssModules', true)
|
||||
const cssModulesResolver = new CSSLoaderResolver(Object.assign({}, baseOptions, {
|
||||
modules: true
|
||||
}))
|
||||
|
||||
const cssModulesLangs = langs.map(lang => [lang, new RegExp(`\\.module\\.${lang}`)])
|
||||
const cssModulesLangs = langs.map(lang => [lang, new RegExp(`\\.module\\.${lang}$`)])
|
||||
for (const cssModulesLang of cssModulesLangs) {
|
||||
const [lang, test] = cssModulesLang
|
||||
const rule = resolver[lang](test)
|
||||
const rule = cssModulesResolver[lang](test)
|
||||
const context = webpackConfig.module
|
||||
.rule(`${lang}-module`)
|
||||
.test(rule.test)
|
||||
|
||||
@@ -4,13 +4,19 @@ const schema = createSchema(joi => joi.object({
|
||||
baseUrl: joi.string(),
|
||||
outputDir: joi.string(),
|
||||
compiler: joi.boolean(),
|
||||
cssModules: joi.boolean(),
|
||||
vueLoaderOptions: joi.object(),
|
||||
productionSourceMap: joi.boolean(),
|
||||
cssSourceMap: joi.boolean(),
|
||||
extractCSS: joi.boolean(),
|
||||
vueLoader: joi.object(),
|
||||
css: joi.object({
|
||||
modules: joi.boolean(),
|
||||
extract: joi.boolean(),
|
||||
sourceMap: joi.boolean(),
|
||||
loaderOptions: joi.object({
|
||||
sass: joi.object(),
|
||||
less: joi.object(),
|
||||
stylus: joi.object()
|
||||
})
|
||||
}),
|
||||
devServer: joi.object(),
|
||||
|
||||
// known options from offical plugins
|
||||
lintOnSave: joi.boolean(),
|
||||
pwa: joi.object()
|
||||
@@ -23,7 +29,7 @@ exports.validate = options => validate(
|
||||
{ allowUnknown: true }
|
||||
)
|
||||
|
||||
exports.defaults = {
|
||||
exports.defaults = () => ({
|
||||
// project deployment base
|
||||
baseUrl: '/',
|
||||
|
||||
@@ -33,20 +39,20 @@ exports.defaults = {
|
||||
// boolean, use full build?
|
||||
compiler: false,
|
||||
|
||||
// apply css modules to CSS files that doesn't end with .module.css?
|
||||
cssModules: false,
|
||||
|
||||
// vue-loader options
|
||||
vueLoaderOptions: {},
|
||||
vueLoader: {},
|
||||
|
||||
// sourceMap for production build?
|
||||
productionSourceMap: true,
|
||||
|
||||
// enable css source map?
|
||||
cssSourceMap: false,
|
||||
|
||||
// boolean | Object, extract css?
|
||||
extractCSS: true,
|
||||
css: {
|
||||
// boolean | Object, extract css?
|
||||
extract: true,
|
||||
// apply css modules to CSS files that doesn't end with .mdoule.css?
|
||||
modules: false,
|
||||
sourceMap: false,
|
||||
loaderOptions: {}
|
||||
},
|
||||
|
||||
// whether to use eslint-loader
|
||||
lintOnSave: false,
|
||||
@@ -62,4 +68,4 @@ exports.defaults = {
|
||||
before: app => {}
|
||||
*/
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
* https://github.com/egoist/webpack-handle-css-loader
|
||||
* The MIT License (MIT)
|
||||
* Copyright (c) EGOIST <0x142857@gmail.com> (github.com/egoist)
|
||||
*
|
||||
* Modified by Yuxi Evan You
|
||||
*/
|
||||
|
||||
const ExtractTextPlugin = require('extract-text-webpack-plugin')
|
||||
@@ -9,58 +11,42 @@ const ExtractTextPlugin = require('extract-text-webpack-plugin')
|
||||
module.exports = class CSSLoaderResolver {
|
||||
/**
|
||||
* @param {Object} options
|
||||
* @param {string} [options.cssLoader='css-loader'] css-loader name or path.
|
||||
* @param {Object|boolean} [options.postcss=undefined] Options for postcss-loader.
|
||||
* @param {boolean} [options.sourceMap=undefined] Enable sourcemaps.
|
||||
* @param {boolean} [options.modules=undefined] Enable CSS modules.
|
||||
* @param {boolean} [options.extract=undefined] Extract CSS.
|
||||
* @param {boolean} [options.minimize=undefined] Minimize CSS.
|
||||
* @param {boolean} [options.cssModules=undefined] Enable CSS modules.
|
||||
* @param {Object} [options.loaderOptions={}] Options to pass on to loaders.
|
||||
*/
|
||||
constructor ({
|
||||
postcss,
|
||||
sourceMap,
|
||||
modules,
|
||||
extract,
|
||||
minimize,
|
||||
cssModules
|
||||
loaderOptions
|
||||
} = {}) {
|
||||
this.postcss = true // true by default, turned off if generating for vue-loader
|
||||
this.cssLoader = 'css-loader'
|
||||
this.fallbackLoader = 'vue-style-loader'
|
||||
this.postcss = postcss
|
||||
this.sourceMap = sourceMap
|
||||
this.extract = extract
|
||||
this.minimize = minimize
|
||||
this.cssModules = cssModules
|
||||
this.modules = modules
|
||||
this.loaderOptions = loaderOptions || {}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set value of instance option
|
||||
* @param {string} key
|
||||
* @param {any} value
|
||||
*/
|
||||
set (key, value) {
|
||||
this[key] = value
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the rule for specific loader
|
||||
* @param {RegExp} [test=undefined] File matcher
|
||||
* @param {RegExp} [loader=undefined] Loader name or path to it
|
||||
* @param {any} [options=undefined] Options for relevant loader
|
||||
* @return {Object} {@link https://webpack.js.org/configuration/module/#rule webpack Rule}
|
||||
*/
|
||||
getLoader (test, loader, options = {}) {
|
||||
const cssLoaderOptions = {
|
||||
sourceMap: this.sourceMap,
|
||||
minimize: this.minimize
|
||||
}
|
||||
|
||||
if (this.cssModules) {
|
||||
if (this.modules) {
|
||||
cssLoaderOptions.modules = true
|
||||
cssLoaderOptions.importLoaders = 1
|
||||
cssLoaderOptions.localIdentName = '[name]_[local]__[hash:base64:5]'
|
||||
}
|
||||
|
||||
if (loader === 'css-loader') {
|
||||
if (loader === 'css') {
|
||||
Object.assign(cssLoaderOptions, options)
|
||||
}
|
||||
|
||||
@@ -69,7 +55,7 @@ module.exports = class CSSLoaderResolver {
|
||||
options: cssLoaderOptions
|
||||
}]
|
||||
|
||||
if (loader !== 'postcss-loader' && this.postcss !== false) {
|
||||
if (loader !== 'postcss' && this.postcss !== false) {
|
||||
use.push({
|
||||
loader: 'postcss-loader',
|
||||
options: {
|
||||
@@ -78,13 +64,12 @@ module.exports = class CSSLoaderResolver {
|
||||
})
|
||||
}
|
||||
|
||||
if (loader && loader !== 'css-loader') {
|
||||
if (loader && loader !== 'css') {
|
||||
use.push({
|
||||
loader,
|
||||
options: {
|
||||
...options,
|
||||
loader: loader + '-loader',
|
||||
options: Object.assign({}, this.loaderOptions[loader] || {}, options, {
|
||||
sourceMap: this.sourceMap
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -102,92 +87,43 @@ module.exports = class CSSLoaderResolver {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the rule for css files
|
||||
* @param {RegExp} [test=/\.css$/] File matcher
|
||||
* @param {any} [options=undefined] Options for css-loader
|
||||
* @return {Object} {@link https://webpack.js.org/configuration/module/#rule webpack Rule}
|
||||
*/
|
||||
css (test, options) {
|
||||
test = test || /\.css$/
|
||||
return this.getLoader(test, 'css-loader', options)
|
||||
css (test = /\.css$/) {
|
||||
return this.getLoader(test, 'css')
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the rule for sass files
|
||||
* @param {RegExp} [test=/\.sass$/] File matcher
|
||||
* @param {any} [options=undefined] Options for sass-loader, `indentedSyntax` for sass-loader is `true` here
|
||||
* @return {Object} {@link https://webpack.js.org/configuration/module/#rule webpack Rule}
|
||||
*/
|
||||
sass (test, options = {}) {
|
||||
test = test || /\.sass$/
|
||||
return this.getLoader(test, 'sass-loader', {
|
||||
indentedSyntax: true,
|
||||
...options
|
||||
sass (test = /\.sass$/) {
|
||||
return this.getLoader(test, 'sass', {
|
||||
indentedSyntax: true
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the rule for scss files
|
||||
* @param {RegExp} [test=/\.scss$/] File matcher
|
||||
* @param {any} [options=undefined] Options for sass-loader
|
||||
* @return {Object} {@link https://webpack.js.org/configuration/module/#rule webpack Rule}
|
||||
*/
|
||||
scss (test, options) {
|
||||
test = test || /\.scss$/
|
||||
return this.getLoader(test, 'sass-loader', options)
|
||||
scss (test = /\.scss$/) {
|
||||
return this.getLoader(test, 'sass')
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the rule for less files
|
||||
* @param {RegExp} [test=/\.less$/] File matcher
|
||||
* @param {any} [options=undefined] Options for less-loader
|
||||
* @return {Object} [Rule] {@link https://webpack.js.org/configuration/module/#rule webpack Rule}
|
||||
*/
|
||||
less (test, options) {
|
||||
test = test || /\.less$/
|
||||
return this.getLoader(test, 'less-loader', options)
|
||||
less (test = /\.less$/) {
|
||||
return this.getLoader(test, 'less')
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the rule for stylus files
|
||||
* @param {RegExp} [test=/\.stylus$/] File matcher
|
||||
* @param {any} [options=undefined] Options for stylus-loader
|
||||
* @return {Object} {@link https://webpack.js.org/configuration/module/#rule webpack Rule}
|
||||
*/
|
||||
stylus (test, options) {
|
||||
test = test || /\.stylus$/
|
||||
return this.getLoader(test, 'stylus-loader', options)
|
||||
styl (test = /\.styl$/) {
|
||||
return this.getLoader(test, 'stylus')
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the rule for styl files
|
||||
* @param {RegExp} [test=/\.styl$/] File matcher
|
||||
* @param {any} [options=undefined] Options for stylus-loader
|
||||
* @return {Object} {@link https://webpack.js.org/configuration/module/#rule webpack Rule}
|
||||
*/
|
||||
styl (test, options) {
|
||||
test = test || /\.styl$/
|
||||
return this.getLoader(test, 'stylus-loader', options)
|
||||
stylus (test = /\.stylus$/) {
|
||||
return this.getLoader(test, 'stylus')
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `loaders` options for vue-loader
|
||||
* @param {any} [options={}] Options for relevant loaders
|
||||
* @return {Object}
|
||||
* @example
|
||||
* handleLoader.vue({
|
||||
* scss: {},
|
||||
* less: {}
|
||||
* })
|
||||
*/
|
||||
vue (options = {}) {
|
||||
vue () {
|
||||
const originalPostcss = this.postcss
|
||||
const originalModules = this.modules
|
||||
this.postcss = false
|
||||
this.cssModules = false
|
||||
this.modules = false
|
||||
const loaders = {}
|
||||
for (const lang of ['css', 'sass', 'scss', 'less', 'stylus', 'styl']) {
|
||||
loaders[lang] = this[lang](null, options[lang]).use
|
||||
loaders[lang] = this[lang]().use
|
||||
}
|
||||
this.postcss = originalPostcss
|
||||
this.modules = originalModules
|
||||
return loaders
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
"copy-webpack-plugin": "^4.3.1",
|
||||
"cross-spawn": "^5.1.0",
|
||||
"css-loader": "^0.28.8",
|
||||
"deepmerge": "^2.0.1",
|
||||
"escape-string-regexp": "^1.0.5",
|
||||
"extract-text-webpack-plugin": "^3.0.2",
|
||||
"file-loader": "^1.1.6",
|
||||
|
||||
@@ -2979,6 +2979,10 @@ deepmerge@^1.5.2:
|
||||
version "1.5.2"
|
||||
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-1.5.2.tgz#10499d868844cdad4fee0842df8c7f6f0c95a753"
|
||||
|
||||
deepmerge@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-2.0.1.tgz#25c1c24f110fb914f80001b925264dd77f3f4312"
|
||||
|
||||
default-require-extensions@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-1.0.0.tgz#f37ea15d3e13ffd9b437d33e1a75b5fb97874cb8"
|
||||
|
||||
Reference in New Issue
Block a user