Solución:
- Vue-cli: v3.11.0
- paquete web: v4.40.2
- babel: 7.6.0
- nodo: v10.16.3
Esta noche me encontré con una situación similar en la que quería mover algunas bibliotecas personalizadas a un directorio de bibliotecas compartido externo para un desarrollo ágil y pruebas simuladas. Comencé a aprender el ecosistema de Vue / webpack hace unas dos semanas, y definitivamente puedo decir que ha sido una aventura con webpack siendo una bestia desalentadora al descubrir todas las perillas y botones místicos que deben alinearse correctamente.
./devel (webpack alias: TTlib)
+-- lib
| +-- widget.js
| +-- frobinator.js
| +-- suckolux3000.js
+-- share (suckolux3000.js taps into this directory)
| +-- imgs
| +-- icons
| | +-- img
| | +-- svg
+-- MainProject
| +-- vue.config.js
| +-- package.json
| +-- node_modules
| +-- src
+-- TestProject
| +-- vue.config.js
| +-- package.json
| +-- node_modules
| +-- src
Mi preocupación era asegurarme de que el paquete web HMR funcionara, y puedo decir que estuvo cerca, pero no fue lo suficientemente lejos. Afortunadamente, la solución fue bastante simple.
Aquí estan mis vue.config.js
adiciones:
module.exports = {
configureWebpack: {
resolve: {
alias: {
'TTlib': '/devel/lib'
},
modules: ['/devel/lib']
},
resolveLoader: {
modules: ['/devel/lib']
}
}
};
Ahora, desde cualquiera de mis * componentes del proyecto, puedo usar:
import frobinator from 'TTlib/frobinator'
Ahora, si edito alguno de los proyectos o (externo) lib, el paquete web HMR se activará y actualizará el demonio ‘yarn serve’ en ejecución y emitirá los cambios que he realizado.
¡Espero que ayude!
**** Actualizar ****
Así que esto fue un infierno. Para mí, esta configuración es la configuración ideal para un equipo pequeño (1-4). No desea lidiar con el empaquetado de npm o la creación de un repositorio adicional si ya tiene un repositorio principal (monolítico) con proyectos secundarios en él. Desea poder desarrollar y depurar los componentes directamente en sus proyectos. Mucho más rápido que actualizar, empaquetar, succionar en otro paquete. Finalmente conseguí que todo funcionara excepto el paquete web HMR en proyectos que consumían los componentes de la carpeta Common. esto es lo que terminó funcionando para mí:
agregando a webpack.config.js arriba resuelve:
resolveLoader: {
modules: [path.resolve(__dirname, 'node_modules')],
},
agregando un alias en resolve (webpack.config.js) para la carpeta común:
'Common': path.resolve(__dirname, '../Common') <- this is the root of my mono repo
modificando mi salida en webpack.config.js (agregado publicPath):
output: {
path: path.join(__dirname, bundleOutputDir),
filename: '[name].js',
publicPath: 'dist/'
},
Esto parece funcionar hasta ahora. Esto me permite pegar archivos de componentes .Vue en una carpeta llamada Common que es hermana de todos mis otros archivos de proyecto. Todos los proyectos, incluido el sitio común, en una carpeta de solución principal que es la raíz de mi repositorio de git.
Las alternativas son usar NPM o bit (https://bitsrc.io). Todas estas soluciones parecen más torpes y menos frágiles que las anteriores.
Había estado usando la solución de Terra durante un tiempo para una situación similar y esto funciona bien, pero había una desventaja para mí, es decir, si el código compartido también requiere contenido de node_modules propio, entonces intellisense no funcionó y al construir el proyecto , aparecerían errores (No se puede encontrar el módulo …) a pesar de que todo funciona bien en el navegador. ¿Quizás es porque estoy usando TypeScript? De cualquier manera, usar paquetes separados o herramientas avanzadas como Bit parecía demasiado complicado, así que fui a buscar una solución más simple sin las desventajas.
Puse mis intentos en este repositorio: https://github.com/brease-colin/vue-typescript-shared donde hay una carpeta de proyecto (proyecto1) y tres intentos de carpeta compartida, todos vinculados en project1 al mismo tiempo, todo con sus propias desventajas, pero planeo usar el intento 3 ya que no es realmente una desventaja para nosotros.
Por cierto, hay un problema que era común para los tres, pero tal vez ese era mi VSCode actuando de manera extraña. Si abrió la carpeta raíz en VSCode, entonces Intellisense dentro de los archivos Vue no entendió ninguna de las importaciones de las tres soluciones, mientras que si abrió la carpeta project1 en VSCode, entendió las importaciones de las tres. La siguiente descripción de cada intento asume la apertura de project1 en VSCode.
Los archivos principales para mirar son:
- project1 / src / components / HelloWorld.vue: archivo vue que intenta reutilizar una función de composición compartida y un componente compartido
- project1 / src / data / ProjectDummies.ts: archivo ts que intenta reutilizar un archivo ts compartido
- project1 / tsconfig.json
- project1 / vue.config.js
- compartido[1/2/3]/ componentes / Encabezado[1/2/3].vue: un componente compartido que se importa desde @ vue / composicion-api.
Intento 1: compartido1 con alias @ s1
Esta es una versión mecanografiada de la respuesta de Terra. Solo agregué una ruta y dos incluyen rutas al archivo tsconfig para que intellisense funcione. También revise shared1 / tsconfig.json, porque allí agregué el mismo alias (@ s1), por lo que las referencias entre archivos compartidos van bien.
Pros: no se necesita configuración adicional, todo funciona bien en el navegador, sin advertencias / errores en la consola, puede abrir fácilmente shared1 como carpeta adicional en su espacio de trabajo de VSCode, para que pueda editar todos los archivos compartidos1.
Contras: las referencias a node_modules no funcionan en VSCode y también se emite un error en el terminal para eso. Como tal, no hay intellisense / no hay seguridad de tipos al usar las clases en la carpeta de su proyecto. Esa última parte es una gran estafa para mí.
Intento 2: shared2 con alias @ s2
Para intentar solucionarlo, agregué un package.json a la carpeta compartida e instalé los paquetes requeridos (en este caso: @ vue / composicion-api) para los archivos compartidos. Esto hizo que intellisense funcionara y el error de salida del terminal al compilar también desapareció. Sin embargo, ahora el código se descompone en tiempo de ejecución en el navegador, porque las dependencias se agregan dos veces y las importaciones en la carpeta compartida no se refieren al mismo código de módulo. Esto no dará errores en todos los tipos de dependencias, pero en algunos casos, se inicializan algunas constantes que deberían ser las mismas en todo el código base. Los errores que obtuve fueron:
[Vue warn]: onMounted is called when there is no active component instance to be associated with. Lifecycle injection APIs can only be used during execution of setup().
[Vue warn]: Error in data(): "Error: [vue-composition-api] must call Vue.use(VueCompositionAPI) before using any function."
found in
---> <Header2> at shared2/components/Header2.vue
<HelloWorld> at src/components/HelloWorld.vue
<Home> at src/views/Home.vue
<App> at src/App.vue
<Root>
Intenté arreglar esto cambiando el módulo resolve / resolveLoader, asegurándome de que primero verifique los node_modules del directorio principal antes de intentar buscar la forma ‘normal’, pero no pareció ayudar.
modules: [
path.resolve(__dirname, 'node_modules'),
'node_modules',
],
¿Quizás alguien tiene una forma de solucionarlo correctamente?
Pros: Intellisense funciona, no más errores de compilación.
Contras: Errores en tiempo de ejecución, ninguna aplicación en funcionamiento, más complejidad / riesgos adicionales al tener que mantener los módulos en los mismos números de versión entre project1 / shared2 para mantener intellisense funcionando de manera consistente.
Intento 3: shared3 con alias @ s3
En cuanto al código, el intento 3 no es tan diferente del intento 1, pero usando un truco simple, todo funciona como yo quería. El truco es usar un enlace simbólico y he usado un paquete npm multiplataforma llamado symlink-dir para hacerlo fácilmente. De hecho, lo agregué como una dependencia de desarrollo al package.json de project1:
npm install --save-dev symlink-dir
Luego, hice el enlace simbólico como se muestra a continuación, lo que debe hacer una vez cada vez que clona el repositorio.
npx symlink-dir ../shared3/ shared3/
Ahora, para evitar registrar el código dos veces, deberá agregar una línea a su .gitignore:
// .gitignore
*/shared3/
Debido a que el código compartido ahora está dentro de la carpeta de su proyecto, incluso podría acceder a él sin un alias, pero para permitir que los archivos de la carpeta compartida se accedan entre sí, prefiero un alias fijo, así que lo agregué agregando la siguiente configuración a vue.config.js y tsconfig.json:
// vue.config.js
configureWebpack: {
resolve: {
alias: {
'@s3': path.resolve(__dirname, 'shared3'),
},
}
},
// tsconfig.json
"compilerOptions": {
// only needed for auto completion(?)
"paths": {
"@s3/*": ["shared3/*"],
},
},
Aunque preferiría una solución de configuración única para mejorar shared1, todavía estoy muy contento con este resultado final, ya que funciona perfectamente para nosotros como un equipo pequeño.
Pros: Sin advertencias, errores, etc .: todo funciona como si el código estuviera en el proyecto, que es el caso, sin dejar de tener el código accesible en otros proyectos.
Contras: Cada desarrollador necesita crear el enlace simbólico manualmente antes de que su código se compile / funcione con intellisense. Por otra parte, también tienen que ejecutar npm install para eso.