CopyWebpackPlugin not copying files when running dev server - vue.js

what I am trying to achieve
I am trying to synchronise locale files from a yarn workspace to multiple Vue apps in a monorepo so they can be used with i18next in each app. They need to be:
kept in sync during development
automatically updated when the translation files get updated
have them eventually in the dist folder so that they get deployed with the rest of the app (which should happen automatically when the files are in the public folder)
In order to keep the bundle size small, I can't just bundle the whole package - the files need to be copied individually with their original file names and stored in the public folder of each app and the UI library.
the problem
I am trying to configure CopyWebpackPlugin, but I am either
just getting an initial copy from translation/locales to public/locales on starting up the dev server
or the dev server ends up in a loop when I try to enable the writeToDisk option, plus it starts flooding the dist folder with hot reload files.
my vue.config.js *
module.exports = {
devServer: {
writeToDisk: true,
},
configureWebpack: {
plugins: [
new CopyPlugin({
patterns: [
{
from: `${path.dirname(
require.resolve(`#namespace/translations/package.json`)
)}/locales`,
to: "./public/locales",
toType: "dir",
},
],
}),
],
},
*based on instructions from https://webpack.js.org/plugins/copy-webpack-plugin/, it includes a reference to yarn workspaces
running yarn serve with this config results in a loop. The correct files are copied to the ./public folder, but at the same time, it creates the ./dist folder and floods it with ...hot-update.json files.
if I run yarn build the first time, the locale files get copied to the ./public folder, but not to the ./dist folder (so it seems it copies the files at the end of the process, so the latest files aren't included in the ./dist folder
current folder structure
Monorepo
└── packages
├── applications
│ ├── app1
│ │ ├── public
│ │ └── dist
│ ├── app2
│ └── ...
└── common
├── translations
│ └── locales
│ ├── en-GB
│ │ └── common.json
│ └── de-DE
├── ui
└── ...
versions
#vue/cli 4.5.12
webpack#4.46.0
copy-webpack-plugin#6.4.1
Any help with getting this setup to work would be very much appreciated.

Related

Yarn Workspaces seemingly not recognizing directory

Wasn't sure the best verbiage for the title, but basically I have a monorepo setup using yarn workspaces. It works for every other directory I have. Here's my layout to make it easy to visualize
├── root
├── package.json
├── node_modules
├── appsync
│ ├── package.json
├── aurora
│ ├── package.json
├── lambdas
│ ├── lambda-function-1
│ ├── └── package.json
│ ├── lambda-function-2
│ ├── └── package.json
Roughly this is as simple as I can make it without getting into too much unnecessary detail. In my root package.json I have my yarn workspaces setup like so:
"workspaces": {
"packages": [
"./*",
"aurora/*",
"lambdas/**",
]
}
The issue is this:
For every other directory I have. Yarn Workspaces is working perfectly. appsync is covered in the ./* declaration. And I have packages in that package.json that get installed property to the root directory and not in the appsync directory. Same with my lambdas. I define those differently because it wont be covered from the ./* declaration. And this works great too, no issues.
Today I added a new directory, and to my surprise saw modules being installed to aurora and not to the root. So I'm very confused whats wrong with my root package.json thats causing this? Or any ideas I can try to get more information? I have done yarn both at root and in the aurora directory as well, and no matter what I try, it always installs modules to the aurora directory and also adds a yarn.lock file to that directory as well.
Any help is appreciated.

nw.js: index.html in a parent folder

The organization of my project's folder is currently as follows:
Root folder
| media folders
| js folder
| index.html
| NW folder
The package.json NW reads is inside the NW folder, which also contains everything in the SDK archive, but whatever I write doesn't seem to point at index.html. I tried both "main": "./../index.html" and "main": "../index.html", but neither of them works.
What's the correct way to point at index.html in the parent folder? Thanks in advance.
You shouldn't be putting package.json in the NW folder. Put package.json next to index.html (in the root folder) and run NW.js from that folder. Your main would then point to "./index.html".
cd /your/root/folder
mv "NW folder/package.json" .
"./NW folder/nw" .
I would recommend putting all of your project files into a package.nw folder with the package.json inside that. When you open nw.exe it will look for a package.nw folder next to it, and then try to run the app inside it.
YourProject/
├── package.nw/
│ ├── media/
│ ├── js/
│ ├── css/
│ ├── index.html
│ └── package.json
├── locales/
├── swiftshader/
├── nw.dll
├── nw.exe
└── all the other NW.js files...
Then you can just rename nw.exe to MyApp.exe, customize its icon with ResourceHacker, zip up the YourProject folder and send it to a buddy to try out. Then all they have to do is "unzip/double-click".

How to access local images in Electron app with Vue

I have an Electron app that uses Vue for its UI. The app downloads compressed data files from a server. The files contain compressed HTML. The app decompresses and display the HTML. That's all working fine.
The HTML may contain img tags that reference images that are also compressed in the downloaded file. I extract and decompress these images, but then need to a) put them somewhere that the app can see them, and b) construct an img tag that correctly references these images.
Rather than list the dozens of places I've tried to put these images, suffice to say that no matter where I put the images, I don't seem to be able to access them from the app. I get a 404 error, and usually a message saying the app can't reference local resources.
Any suggestions for where the app should store these images, and then how to reference them from img tags?
I have a related problem with images I could reference from the Web, but would prefer to download and cache locally so that the app can display them when there's no internet connection. I feel like if I can solve one of these problems, I can solve them both.
this below setting(s) works for me...
.
├── dist
│ ├── css
│ │ └── app.6cb8b97a.css
│ ├── img
│ │ └── icon.1ba2ae71.png
│ ├── index.html
│ └── js
│ ├── app.08f128b0.js
│ ├── app.08f128b0.js.map
│ ├── chunk-vendors.e396765f.js
│ └── chunk-vendors.e396765f.js.map
├── electron.js
├── package.json
├── package-lock.json
├── public
│ ├── favicon.ico
│ └── index.html
└── src
├── App.vue
├── components
│ ├── _breakpoint.scss
│ └── RoundList.vue
├── img
│ ├── bullet.svg
│ └── icon.png
└── index.js
vue.config.js:
const path = require("path");
module.exports = {
outputDir: path.resolve(__dirname, "./basic_app/dist"),
publicPath: './'
};
part of package.json
"scripts": {
"build:vue": "vue-cli-service build",
"serve:electron": "electron .",
"serve": "concurrently \"yarn build:vue\" \"yarn serve:electron\"",
"build:electron": ""
},
the output: https://i.stack.imgur.com/nKK7y.png

Vue-CLI v3 opinionated project structure

I'm trying to move existing project to Vue and I've used Vue-CLI 3 and installed it locally and then I've generated the project through the following command ./node_modules/.bin/vue create dashboard and I've used the following options:
Check the features needed for your project: Babel, TS, PWA, Router, Vuex, CSS Pre-processors, Linter, Unit, E2E
Use class-style component syntax? Yes
Use Babel alongside TypeScript for auto-detected polyfills? Yes
Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported by default): SCSS/SASS
Pick a linter / formatter config: TSLint
Pick additional lint features: Lint on save
Pick a unit testing solution: Mocha
Pick a E2E testing solution: Cypress
Where do you prefer placing config for Babel, PostCSS, ESLint, etc.? In dedicated config files
Save this as a preset for future projects? No
This will generate the following project structure:
..\Web\.experiment
├── dashboard
| ├── babel.config.js
| ├── cypress.json
| ├── node_modules
| ├── package-lock.json
| ├── package.json
| ├── public
| | ├── favicon.ico
| | ├── img
| | ├── index.html
| | └── manifest.json
| ├── src
| | ├── App.vue
| | ├── assets
| | ├── components
| | ├── main.ts
| | ├── registerServiceWorker.ts
| | ├── router.ts
| | ├── shims-tsx.d.ts
| | ├── shims-vue.d.ts
| | ├── store.ts
| | └── views
| ├── tests
| | ├── e2e
| | └── unit
| ├── tsconfig.json
| └── tslint.json
├── node_modules
├── package-lock.json
└── package.json
Now, I'm having the following issues:
At my company we tend to install all tools that are related to the project as part of the project as opposed to global installs and in this case I couldn't find a way to tell Vue-CLI3 to generate the files directly at the .experiment directory so now we have two node_modules directories as opposed to one as you can see in the structure above.
Our current project structure is something like the following:
..\Web\<domain>\Src\Dashboard\
├── app
├── node_modules
├── package-lock.json
├── package.json
├── tests
├── tsconfig.json
└── tslint.json
And this is really important to us because we have things dependent on this structure so what I did is started to copy/paste things from the generated directory into the project to match our structure.
After I copied/pasted everything and ran npm run serve it started to complain and throws the following errors:
ERROR Failed to compile with 1 errors
17:00:23
This relative module was not found:
* ./src/main.ts in multi (webpack)-dev-server/client?/sockjs-node (webpack)/hot/dev-server.js ./src/main.ts
So I went to the node_modules directory and searched for ./src/main.ts I've found it in ..\Web\<domain>\Src\Dashboard\node_modules\#vue\cli-plugin-typescript\index.js and I have no clue how to configure it so what I did is change the default path of the module to ./app/main.ts and then I got the following error:
ERROR Failed to compile with 1 errors 17:07:52
This dependency was not found:
* #/components/HelloWorld.vue in ./node_modules/cache-loader/dist/cjs.js??ref--13-0!./node_modules/babel-loader/lib!./node_modules/ts-loader??ref--13-2!./node_modules/vue-loader/lib??vue-loader-options!./app/views/Home.vue?vue&type=script&lang=ts
So I changed # to /app because in the comments it says the following
"// # is an alias to /src" but it doesn't really work because then I get a similar error:
ERROR Failed to compile with 1 errors 17:37:33
This dependency was not found:
* /app/components/HelloWorld.vue in ./node_modules/cache-loader/dist/cjs.js??ref--13-0!./node_modules/babel-loader/lib!./node_modules/ts-loader??ref--13-2!./node_modules/vue-loader/lib??vue-loader-options!./app/views/Home.vue?vue&type=script&lang=ts
And I have the following questions:
How can I generate a template in existing directory where a node_modules directory might exist using Vue-CLI v3?
How do I configure the entry point of Vue without messing with the modules themselves? e.g. I want to change ./src/main.ts to ./app/main.ts.
How do I change where # points to?
I read and found that something like vue.config.js exists but then I didn't really understand how to configure it to fit my needs.
I've solved all the issues I had by creating a vue.config.js file at the root of the project and then used the following configuration:
"use strict"
const path = require("path")
module.exports = {
chainWebpack: config => {
const app = config.entry("app");
app.clear();
app.add("./app/main.ts");
},
configureWebpack: {
resolve: {
alias: {
"#": path.resolve("app"),
}
}
}
}

Share node_modules installation between sub-projects, while maintaining separate package.json files

I have the following folder structure:
project
├───components
│ ├───component-one
│ │ package.json
│ │
│ └───component-two
│ │ package.json
│ │
│ └───node_modules
├───node_modules
└───package.json
Project root project folder contains package.json and is intended to have various infrastructural modules installed (Gulp, for example, as the build is centralized).
Each component under components folder is eventually, after build and whatnot, is deployed somewhere to be consumed by an application - using the usual npm install from folder or tarball. For that reason, each component must maintain its own dependencies in its own package.json.
Going the trivial route, installing node_modules into each of the component folders would lead to a crazy amount of duplication, as there may be 100s of components, each installing mostly the same dependencies.
Ideally I would like to:
run, for example, npm install -D <module> in component-one folder
have package.json in that folder updated with the <module>
have <module> installed in the project folder
This can be achieved, to some extent, running (on Windows, in this case) mklink /D node_modules ..\..\node_modules from component-one to create a symlink.
However, symlinks are fragile and finicky, so I'd like to avoid that solution.
Is there an npm solution, via npm link or something that I am missing?