mirror of
https://github.com/vuejs/vue-cli.git
synced 2026-01-14 19:30:14 -06:00
fix: more global resolve fixes + better error message for missing loaders
This commit is contained in:
@@ -10,11 +10,11 @@ module.exports = api => {
|
||||
.add(api.resolve('test'))
|
||||
.end()
|
||||
.use('cache-loader')
|
||||
.loader(require.resolve('cache-loader'))
|
||||
.loader('cache-loader')
|
||||
.options({ cacheDirectory })
|
||||
.end()
|
||||
.use('babel-loader')
|
||||
.loader(require.resolve('babel-loader'))
|
||||
.loader('babel-loader')
|
||||
|
||||
webpackConfig.module
|
||||
.rule('vue')
|
||||
@@ -23,11 +23,11 @@ module.exports = api => {
|
||||
options.loaders = options.loaders || {}
|
||||
options.loaders.js = [
|
||||
{
|
||||
loader: require.resolve('cache-loader'),
|
||||
loader: 'cache-loader',
|
||||
options: { cacheDirectory }
|
||||
},
|
||||
{
|
||||
loader: require.resolve('babel-loader')
|
||||
loader: 'babel-loader'
|
||||
}
|
||||
]
|
||||
return options
|
||||
|
||||
@@ -11,7 +11,7 @@ module.exports = (api, { lintOnSave }) => {
|
||||
.end()
|
||||
.test(/\.(vue|jsx?)$/)
|
||||
.use('eslint-loader')
|
||||
.loader(require.resolve('eslint-loader'))
|
||||
.loader('eslint-loader')
|
||||
.options(Object.assign(options, {
|
||||
formatter: require('eslint/lib/formatters/codeframe')
|
||||
}))
|
||||
|
||||
@@ -24,11 +24,11 @@ module.exports = (api, options) => {
|
||||
// this is pending on the readiness of @babel/preset-typescript.
|
||||
tsRule
|
||||
.use('cache-loader')
|
||||
.loader(require.resolve('cache-loader'))
|
||||
.loader('cache-loader')
|
||||
.options({ cacheDirectory })
|
||||
.end()
|
||||
.use('babel-loader')
|
||||
.loader(require.resolve('babel-loader'))
|
||||
.loader('babel-loader')
|
||||
|
||||
config.module
|
||||
.rule('vue')
|
||||
@@ -41,19 +41,19 @@ module.exports = (api, options) => {
|
||||
if (api.hasPlugin('babel')) {
|
||||
tsRule
|
||||
.use('cache-loader')
|
||||
.loader(require.resolve('cache-loader'))
|
||||
.loader('cache-loader')
|
||||
.options({ cacheDirectory })
|
||||
.end()
|
||||
.use('babel-loader')
|
||||
.loader(require.resolve('babel-loader'))
|
||||
.loader('babel-loader')
|
||||
}
|
||||
tsRule
|
||||
.use('cache-loader-2')
|
||||
.loader(require.resolve('cache-loader'))
|
||||
.loader('cache-loader')
|
||||
.options({ cacheDirectory })
|
||||
.end()
|
||||
.use('ts-loader')
|
||||
.loader(require.resolve('ts-loader'))
|
||||
.loader('ts-loader')
|
||||
.options({
|
||||
transpileOnly: true,
|
||||
appendTsSuffixTo: [/\.vue$/]
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
const path = require('path')
|
||||
const resolve = require('resolve')
|
||||
const { findExisting } = require('./util')
|
||||
|
||||
module.exports = function createConfigPlugin (context, entry) {
|
||||
return {
|
||||
id: '@vue/cli-service-global-config',
|
||||
apply: api => {
|
||||
apply: (api, options) => {
|
||||
api.chainWebpack(config => {
|
||||
// entry is *.vue file, create alias for built-in js entry
|
||||
if (/\.vue$/.test(entry)) {
|
||||
@@ -19,21 +20,29 @@ module.exports = function createConfigPlugin (context, entry) {
|
||||
}
|
||||
}
|
||||
|
||||
// include resolve for deps of this module.
|
||||
// when installed globally, the location may vary depending on
|
||||
// package managers their folder structures for global install.
|
||||
// so we first resolve the location of vue and then trace to the
|
||||
// install location.
|
||||
// ensure loaders can be resolved properly
|
||||
const modulePath = path.resolve(require.resolve('vue'), '../../../')
|
||||
|
||||
config.resolve
|
||||
.modules
|
||||
.add(modulePath)
|
||||
|
||||
config.resolveLoader
|
||||
.modules
|
||||
.add(modulePath)
|
||||
|
||||
// add resolve alias for vue and vue-hot-reload-api
|
||||
// but prioritize versions installed locally.
|
||||
try {
|
||||
resolve.sync('vue', { basedir: context })
|
||||
} catch (e) {
|
||||
const vuePath = path.dirname(require.resolve('vue'))
|
||||
config.resolve.alias
|
||||
.set('vue$', `${vuePath}/${options.compiler ? `vue.esm.js` : `vue.runtime.esm.js`}`)
|
||||
}
|
||||
|
||||
try {
|
||||
resolve.sync('vue-hot-reload-api', { basedir: context })
|
||||
} catch (e) {
|
||||
config.resolve.alias
|
||||
.set('vue-hot-reload-api', require.resolve('vue-hot-reload-api'))
|
||||
}
|
||||
|
||||
// set entry
|
||||
config
|
||||
.entry('app')
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
"@vue/cli-service": "^3.0.0-alpha.2",
|
||||
"chalk": "^2.3.0",
|
||||
"eslint-plugin-vue": "^4.2.0",
|
||||
"resolve": "^1.5.0",
|
||||
"vue": "^2.5.13"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,14 +44,14 @@ module.exports = (api, options) => {
|
||||
.rule('vue')
|
||||
.test(/\.vue$/)
|
||||
.use('vue-loader')
|
||||
.loader(require.resolve('vue-loader'))
|
||||
.loader('vue-loader')
|
||||
.options(Object.assign({}, options.vueLoader))
|
||||
|
||||
webpackConfig.module
|
||||
.rule('images')
|
||||
.test(/\.(png|jpe?g|gif)(\?.*)?$/)
|
||||
.use('url-loader')
|
||||
.loader(require.resolve('url-loader'))
|
||||
.loader('url-loader')
|
||||
.options({
|
||||
limit: 10000,
|
||||
name: `img/[name].[hash:8].[ext]`
|
||||
@@ -63,7 +63,7 @@ module.exports = (api, options) => {
|
||||
.rule('svg')
|
||||
.test(/\.(svg)(\?.*)?$/)
|
||||
.use('file-loader')
|
||||
.loader(require.resolve('file-loader'))
|
||||
.loader('file-loader')
|
||||
.options({
|
||||
name: `img/[name].[hash:8].[ext]`
|
||||
})
|
||||
@@ -72,7 +72,7 @@ module.exports = (api, options) => {
|
||||
.rule('media')
|
||||
.test(/\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/)
|
||||
.use('url-loader')
|
||||
.loader(require.resolve('url-loader'))
|
||||
.loader('url-loader')
|
||||
.options({
|
||||
limit: 10000,
|
||||
name: `media/[name].[hash:8].[ext]`
|
||||
@@ -82,7 +82,7 @@ module.exports = (api, options) => {
|
||||
.rule('fonts')
|
||||
.test(/\.(woff2?|eot|ttf|otf)(\?.*)?$/)
|
||||
.use('url-loader')
|
||||
.loader(require.resolve('url-loader'))
|
||||
.loader('url-loader')
|
||||
.options({
|
||||
limit: 10000,
|
||||
name: `fonts/[name].[hash:8].[ext]`
|
||||
|
||||
@@ -18,9 +18,15 @@ module.exports = api => {
|
||||
.plugin('no-emit-on-errors')
|
||||
.use(require('webpack/lib/NoEmitOnErrorsPlugin'))
|
||||
|
||||
// friendly error plugin displays very confusing errors when webpack
|
||||
// fails to resolve a loader, so we provide custom handlers to improve it
|
||||
const { transformer, formatter } = require('../webpack/resolveLoaderError')
|
||||
webpackConfig
|
||||
.plugin('firendly-errors')
|
||||
.use(require('friendly-errors-webpack-plugin'))
|
||||
.use(require('friendly-errors-webpack-plugin'), [{
|
||||
additionalTransformers: [transformer],
|
||||
additionalFormatters: [formatter]
|
||||
}])
|
||||
|
||||
webpackConfig
|
||||
.plugin('watch-missing')
|
||||
|
||||
@@ -194,7 +194,7 @@ module.exports = (api, options) => {
|
||||
// .rule('vue')
|
||||
// .use('thread-loader')
|
||||
// .before('vue-loader')
|
||||
// .loader(require.resolve('thread-loader'))
|
||||
// .loader('thread-loader')
|
||||
// .options({ name: 'vue' })
|
||||
}
|
||||
})
|
||||
|
||||
25
packages/@vue/cli-service/lib/webpack/resolveLoaderError.js
Normal file
25
packages/@vue/cli-service/lib/webpack/resolveLoaderError.js
Normal file
@@ -0,0 +1,25 @@
|
||||
const chalk = require('chalk')
|
||||
const TYPE = 'cant-resolve-loader'
|
||||
const errorRE = /Can't resolve '(.*loader)'/
|
||||
|
||||
exports.transformer = error => {
|
||||
if (error.webpackError) {
|
||||
const match = error.webpackError.message.match(errorRE)
|
||||
if (match) {
|
||||
return Object.assign({}, error, {
|
||||
type: TYPE,
|
||||
loader: match[1]
|
||||
})
|
||||
}
|
||||
}
|
||||
return error
|
||||
}
|
||||
|
||||
exports.formatter = errors => {
|
||||
errors = errors.filter(e => e.type === TYPE)
|
||||
if (errors.length) {
|
||||
return errors.map(e => {
|
||||
return `Failed to resolve loader: ${chalk.yellow(e.loader)}`
|
||||
}).concat(`\nYou may need to install the missing loader.`)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user