Webpack 使用错误的 node_modules 文件夹 [英] Webpack using wrong node_modules folder
问题描述
我有一个使用 vue 库项目的 vue 客户端项目(vue 库项目也使用了一些 3rd 方包,例如 vue-material).
I have a vue client project that uses a vue library project (the vue library project is also using some 3rd party packages like vue-material).
它们通过客户端项目的 Package.json 链接,就像这样 "lib": "file:../lib"
并且我正在使用 import Comp from 在客户端项目中导入组件"lib/src/components/Comp";
They are linked via the client project's Package.json like this "lib": "file:../lib"
and I am importing components in the client project using import Comp from "lib/src/components/Comp";
问题是,当我使用 Webpack 构建客户端项目时,我库中的文件使用 lib/node_modules/vue
而不是 node_modules/vue
这会导致双 vue实例化.
The problem is that when I build the client project using Webpack, the files in my library use lib/node_modules/vue
instead of node_modules/vue
which causes double vue instancing.
有谁知道为什么当我从客户端文件夹使用 webpack 构建时,它会在我的库文件夹中查找 vue 包?有没有办法解决这个问题?
Anyone has any idea why when I am using webpack build from the client folder, it looks for vue package in my library folder? and is there a way to get around that?
我的 webpack.config
My webpack.config
"use strict";
const path = require("path");
const utils = require("./utils");
const config = require("../config");
const vueLoaderConfig = require("./vue-loader.conf");
function resolve(dir) {
return path.join(__dirname, "..", dir);
}
module.exports = {
entry: {
app: ["babel-polyfill", "./src/main.js"]
},
output: {
path: config.build.assetsRoot,
filename: "[name].js",
publicPath: process.env.NODE_ENV === "production" ? config.build.assetsPublicPath : config.dev.assetsPublicPath
},
resolve: {
extensions: [".js", ".vue", ".json"],
alias: {
vue$: "vue/dist/vue.esm.js",
"@": resolve("src"),
src: resolve("src"),
assets: resolve("src/assets"),
components: resolve("src/components"),
utilities: resolve("src/utilities"),
directives: resolve("src/directives"),
plugins: resolve("src/plugins"),
data: resolve("src/data"),
"vuex-store": resolve("src/store"),
"lib": resolve("node_modules/lib")
}
},
module: {
rules: [
{
test: /\.(js|vue)$/,
loader: "eslint-loader",
enforce: "pre",
include: [resolve("src")],
options: {
formatter: require("eslint-friendly-formatter")
}
},
{
test: /\.vue$/,
loader: "vue-loader",
options: vueLoaderConfig
},
{
test: /\.js$/,
loader: "babel-loader",
include: [resolve("src"), resolve("../lib/src")]
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: "url-loader",
options: {
limit: 10000,
name: utils.assetsPath("img/[name].[hash:7].[ext]")
}
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
loader: "url-loader",
options: {
limit: 10000,
name: utils.assetsPath("media/[name].[hash:7].[ext]")
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: "base64-font-loader",
options: {
limit: 10000,
name: utils.assetsPath("fonts/[name].[hash:7].[ext]")
}
},
{
test: /\.ico$/,
loader: "file-loader?name=[name].[ext]"
}
]
}
};
我客户的主要入口
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
// Core Imports
import Vue from 'vue'
import App from './App'
// Plugins
import { ComponentsPlugin } from "lib/src/components";
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
store,
template: '<App/>',
components: { App }
})
推荐答案
当我用完这个问题的解决方案时,我决定调试 webpack 的编译器.
As I ran out of solutions to this problem I decided to debug webpack's compiler.
似乎 webpack 使用了一个名为enhanced-resolve"的库(我们实际上在 webpack 的 resolve:{}
部分将参数发送到该库).使用 resolve.alias
属性,我们可以将任何 require
重定向到我们想要的任何文件夹.
It seems webpack uses a library called 'enhanced-resolve' (We actually send parameters to that library in our webpack's resolve:{}
section). And using the resolve.alias
property we can redirect any require
to any folder we want.
所以要将任何 require("vue")
重定向到我自己的 vue.esm.js,我只需要添加一个这样的条目(我最初有那行,但它指向相对路径而不是绝对路径):
So to redirect any require("vue")
to my own vue.esm.js, all I need is to add an entry like this (I originally had that line but it was pointing to a relative path rather than an absolute path):
resolve: {
alias: {
vue$: resolve("node_modules/vue/dist/vue.esm.js"),
}
}
注意库名称末尾的 $,它表示包只有 1 个模块,因此任何名称为vue"或vue"子目录的 require 都应使用别名解析.
Note the $ at the end of the library name, It signals enhanced-resolve that the package only has 1 module so any require whos name is "vue" or a sub-directory of "vue" should be parsed using the alias.
Enhanced-Resolve - ResolverFactory.js
if(/\$$/.test(alias)) {
onlyModule = true;
....
}
Enhanced-Resolve - AliasPlugin.js
// InnerRequest is the path (vue/dist/vue.esm.js)
// name is the alias name without the $ (vue)
if(innerRequest === name || (!onlyModule && startsWith(innerRequest, name + "/"))) {
continue resolving....
}
这篇关于Webpack 使用错误的 node_modules 文件夹的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!