How to develop/debug two apps with shared components using vue3 and vite? - vuejs3

I'm building a couple of apps with vue3 and vite, using some shared components. The production build process works OK but I'm having a problem with dev/debug. The Vite docs (for multi-page apps) says
"During dev, simply navigate or link to /nested/ - it works as
expected, just like for a normal static file server."
but I don't know what this means - how do I link to a sub folder? I have added /src/app1 to url in launch.json, but it has no effect. I have also tried using cd src\app1 in the terminal before running npm run dev
"version": "0.2.0",
"configurations": [
{
"type": "firefox",
"request": "launch",
"name": "vuejs: firefox -width 300 -height 600 -P default",
"url": "http://localhost:5173/src/app1",
"webRoot": "${workspaceFolder}",
"pathMappings": [
{
"url": "file:///C:",
"path": "c:"
}
]
}
]
(This launch.json works well with a simple single-page app).
What happens with trying to debug one of the apps is that the project launches but with an empty index.html (i.e. a blank screen with no errors). I'm pretty sure the basic project structure is OK because (as I said) the build process works; I get two separate outputs of html+css+js both of which work as expected, with the correct shared components.
Also, if I tell the Vite server to automatically open the page (as I have done in my vite.config.js below) the page opens correctly - although without a debugger attached of course. So I guess that the settings in launch.json are incorrect.
The project structure is:
-src
-app1
-app.vue
-index.html
-main.js
-app2
-app.vue
-index.html
-main.js
-assets
...
-shared
-components
-shared.vue
If I have just one index.html, moved up a level, I can debug each app but only by editing it every time to point to a different main.js and to change the title, which seems a laborious way of approaching the task.
Below is my vite config. The extra lines in alias were added as an attempt to solve the problem but they are probably incorrect (or unneccesary)
import { fileURLToPath, URL } from 'node:url'
import { resolve } from 'path'
import { defineConfig } from 'vite'
import vue from '#vitejs/plugin-vue'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
server: {
base: '/src/app1',
open: '/src/app1/index.html',
},
resolve: {
alias: {
vue: 'vue/dist/vue.esm-bundler.js',
'#': fileURLToPath(new URL('./src', import.meta.url)),
app1: fileURLToPath(new URL('./src/app1', import.meta.url)),
app2: fileURLToPath(new URL('./src/app2', import.meta.url)),
// shared: fileURLToPath(new URL('./src/shared/components', import.meta.url)),
}
},
build: {
rollupOptions: {
input: {
app1: resolve(__dirname, './src/app1/index.html'),
app2: resolve(__dirname, './src/app2/index.html'),
},
},
},
})

I've made things more complex than neccesary because I missed the important setting. In vite.config.js, it's important to define root to point to where each index.html is found. So for my structure above, the config file looks like
import { defineConfig } from 'vite'
import vue from '#vitejs/plugin-vue'
export default defineConfig({
plugins: [vue() ],
root: "src\app1",
resolve: {
alias: {
vue: 'vue/dist/vue.esm-bundler.js',
}
}
})
In the process I've also swapped from Firefox to Chrome for debug (I was getting a lot of irrelevant error messages from Firefox), and my launch.json is now simply
{
"version": "0.2.0",
"configurations": [
{
"type": "chrome",
"request": "launch",
"name": "Launch Chrome against localhost",
"url": "http://localhost:5173",
"webRoot": "${workspaceFolder}",
}
]
}
It doesn't really matter what the file structure looks like, as long as within each file its dependencies are correctly addressed. The only important bit is the root. Simply by changing that from 'app1' to 'app2' will switch both the debug and the build to the correct folders, with the release (built) files being stored in subfolders of 'app1' and 'app2' independently.
It would be easy to extend this to have more than 2 apps each sharing the same common components.

Related

where to place next/font inside nx workspace

i have a NX workspace with nextjs and a few libraries. im using mui as the component library. im also using #next/font to load a google font.
I have created a library for the mui theme, i which i export a singel theme i want to use across entire application. there is no problem with the theme except for the font part. i did it exactly like this, https://github.com/mui/material-ui/blob/master/examples/nextjs-with-typescript/src/theme.ts this example comes from the miu repo. i get the following error:
Font loaders cannot be used from within node_modules.
Location: ..\..\libs\shared\ui\src\lib\shared-ui.tsx
this is my project.json for the nx workspace
{
"name": "shared-ui",
"$schema": "../../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "libs/shared/ui/src",
**"projectType": "library",**
"tags": [],
"targets": {
"lint": {
"executor": "#nrwl/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": ["libs/shared/ui/**/*.{ts,tsx,js,jsx}"]
}
},
"test": {
"executor": "#nrwl/jest:jest",
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
"options": {
"jestConfig": "libs/shared/ui/jest.config.ts",
"passWithNoTests": true
}
}
}
}
as u can see it is a lib.
how can i use the next/font with mui inside a NX workspace?
I got the same error with similar setup (themes coming from a shared ui Nx lib). I worked around it by passing in the font as a parameter under /apps to the theme provider component under /libs. I guess Next needs the font loader to be called in the app itself to do its magic.
import { Roboto } from '#next/font/google';
import { CustomThemeProvider } from '#shared-ui';
...
const roboto = Roboto({...});
...
<CustomThemeProvider fontFamily={roboto.style.fontFamily}>{children}</CustomThemeProvider>

Linaria + Next.js + Path Aliases

I wanted to give Linaria (utilizing next-linaria) a try, but I'm currently stuck to get it working in any of my Next.js projects (that also use Typescript by the way).
The root of evil seems to be path aliases that are supported by Next.js by default.
tsconfig.json
...
"compilerOptions": {
...
"paths": {
"~/*": [
"src/*"
]
}
},
When just installing Linaria and next-linaria, I get an error like this:
Error: Can't resolve '~/layout/main/MainWrapper' in '[...]\src\layout\main'
I already know that Linaria stated to not support any other module aliasing than #babel-plugin-module-resolver or webpack. However, I can't get either of those to work.
I tried #babel-plugin-module-resolver and put same path configuration (and some other tries) to .babelrc without success.
"plugins": [
["module-resolver", {
"alias": {
"~/*": [
"src/*"
]
}
}]
]
I also tried doing the same with webpack aliases.
next.config.js
module.exports = withLinaria({
webpack: (config, { dev }) => {
config.resolve.alias = {
...config.resolve.alias,
"~/": path.resolve(__dirname, "./src/"),
};
return config;
},
});
The default project structure of Next.js looks like this:
/
/pages (contains entry points for each route)
/src (contains regular react components)
So, I'm kindly asking if anyone can tell us how to use path aliasing with Next + Linaria.

Include node_modules css in Vuejs application that uses scss

I have deployed my application to aws and I see that the application renders fine, except that the syncfusion controls do not render correctly. Google chrome console does not show any errors.
The application renders correctly in my local machine.
To fix this, it was suggested I move the import '#syncfusion/**/styles/material.css' statements in the individual vue component to App.vue (as documented here). I however get a "Failed to resolve loader: sass-loader, You may need to install it" error(the application has node-sass, sass-loader installed already).
How should I include css files along with scss files, in my application?
Before: vocabulary.vue:
<script>
import '#syncfusion/ej2-base/styles/material.css';
import '#syncfusion/ej2-vue-inputs/styles/material.css';
package.json:
"devDependencies": {
"node-sass": "^4.12.0",
"sass-loader": "^7.1.0",
}
vue.config.js:
module.exports = {
publicPath: '/',
transpileDependencies: [
'vue-echarts',
'resize-detector'
],
configureWebpack: {
devtool: 'source-map',
optimization: {
splitChunks: {
chunks: 'all'
}
}
}
}
App.Vue:
<style>
#import "../node_modules/#syncfusion/ej2-base/styles/material.css";
#import "../node_modules/#syncfusion/ej2-vue-inputs/styles/material.css";
</style>
Deleting the npm packages and re-installing them again fixed the issue.

Why does there appear to be non deterministic behavior trying to load a babel plugin in a nextjs project? Next - Babel

I have a nextjs app with redux.
When I try to use the ?? operator in my pages/index, it works as it should.
I then tried to load up a redux store with a bunch of reducers. When I hit the ?? in a reducer file, I get this error:
Support for the experimental syntax 'optionalChaining' isn't currently enabled (71:32):
I also get the error in any other file: component, actions and reducers. It is only directly in the pages/* that the plugin is working properly.
My app is using next#9.1.1 and redux#4.0.4. Here is my .babelrc file:
"env": {
"development": {
"presets": ["next/babel"],
"plugins": [
"#babel/plugin-proposal-optional-chaining",
"#babel/plugin-proposal-nullish-coalescing-operator",
[
"styled-components",
{ "ssr": true, "displayName": true, "preprocess": false }
]
]
}
}
}
Is there something that would override my babel config for certain files? If so, what am I missing? What else should I look at?

Making sure vendor JS is called before custom JS (WordPress Sage)

I can't find how to make vendor scripts load before my own scripts. In manifest.json I tried:
"dependencies": {
"main.js": {
"files": [
"scripts/vendor_script.js",
"scripts/custom_script.js"
],
"main": true
},
Doesn't work: vendor script is called after my custom script. Also tried:
"dependencies": {
"plugins.js": {
"files": [
"scripts/vendor/owl.carousel.min.js"
]
},
"main.js": {
"files": [
"scripts/main.js"
],
"main": true
},
Same. Any suggestion?
[EDIT] my current manifest.json file, where I followed the advice from https://discourse.roots.io/t/custom-javascript-in-manifest-json-and-building-out-into-a-single-file/3316:
{
"dependencies": {
"main.js": {
"vendor": [
"scripts/vendor/owl.carousel.min.js"
],
"files": [
"scripts/main.js"
],
"main": true
},
"main.css": {
"files": [
"styles/main.scss",
"styles/vendor/font-awesome.min.css",
"styles/vendor/owl.carousel.min.css"
],
"main": true
},
"customizer.js": {
"files": [
"scripts/customizer.js"
]
},
"jquery.js": {
"bower": ["jquery"]
}
},
"config": {
"devUrl": "http://127.0.0.1/pot/"
}
}
[EDIT #2]
$ node
> require('asset-builder')('./assets/manifest.json').globs.js
require('asset-builder')('./assets/manifest.json').globs.js
[ { type: 'js',
name: 'main.js',
globs:
[ 'D:\\EasyPHP\\www\\pot\\wp-content\\themes\\pot\\bower_components\\bootstrap-sass\\assets\\javascripts\\bootstrap\\transition.js',
'D:\\EasyPHP\\www\\pot\\wp-content\\themes\\pot\\bower_components\\bootstrap-sass\\assets\\javascripts\\bootstrap\\alert.js',
'D:\\EasyPHP\\www\\pot\\wp-content\\themes\\pot\\bower_components\\bootstrap-sass\\assets\\javascripts\\bootstrap\\button.js',
'D:\\EasyPHP\\www\\pot\\wp-content\\themes\\pot\\bower_components\\bootstrap-sass\\assets\\javascripts\\bootstrap\\carousel.js',
'D:\\EasyPHP\\www\\pot\\wp-content\\themes\\pot\\bower_components\\bootstrap-sass\\assets\\javascripts\\bootstrap\\collapse.js',
'D:\\EasyPHP\\www\\pot\\wp-content\\themes\\pot\\bower_components\\bootstrap-sass\\assets\\javascripts\\bootstrap\\dropdown.js',
'D:\\EasyPHP\\www\\pot\\wp-content\\themes\\pot\\bower_components\\bootstrap-sass\\assets\\javascripts\\bootstrap\\modal.js',
'D:\\EasyPHP\\www\\pot\\wp-content\\themes\\pot\\bower_components\\bootstrap-sass\\assets\\javascripts\\bootstrap\\tooltip.js',
'D:\\EasyPHP\\www\\pot\\wp-content\\themes\\pot\\bower_components\\bootstrap-sass\\assets\\javascripts\\bootstrap\\popover.js',
'D:\\EasyPHP\\www\\pot\\wp-content\\themes\\pot\\bower_components\\bootstrap-sass\\assets\\javascripts\\bootstrap\\scrollspy.js',
'D:\\EasyPHP\\www\\pot\\wp-content\\themes\\pot\\bower_components\\bootstrap-sass\\assets\\javascripts\\bootstrap\\tab.js',
'D:\\EasyPHP\\www\\pot\\wp-content\\themes\\pot\\bower_components\\bootstrap-sass\\assets\\javascripts\\bootstrap\\affix.js',
'scripts/vendor/owl.carousel.min.js',
'assets/scripts/main.js' ] },
{ type: 'js',
name: 'customizer.js',
globs: [ 'assets/scripts/customizer.js' ] },
{ type: 'js',
name: 'jquery.js',
globs: [ 'D:\\EasyPHP\\www\\pot\\wp-content\\themes\\pot\\bower_components\\jquery\\dist\\jquery.js' ] } ]
The script I'm trying to use is Owl Carousel. If I add the following in head.php it works fine:
<script src="<?php bloginfo("template_url"); ?>/assets/scripts/vendor/owl.carousel.min.js" type="text/javascript" charset="utf-8"></script>
If, instead, I set my manifest.json as shown previously I get a ".owlCarousel is not a function" in Firebug and my slider doesn't work.
Note: I didn't use Bowel, it's not mandatory in regular Sage workflow right? I just copied owl.carousel.min.js into assets/scripts/vendor/.
On a fresh Sage 8 installation I was able to quickly install OwlCarousel using Bower, exactly as described in the Sage documentation without any issue; its script and styles were both correctly included before project scripts and styles.
Font Awesome requires a Bower override because its default Bower main property instructs Bower to use a LESS and a SCSS file; once I set it to just use SCSS it worked fine. Sage 8 ships with a working set of Bower overrides which you should use as an example. See here.
Something else is going wrong with your scripts or your asset builder setup if you're unable to manually add scripts in the correct order. I suspect your asset paths may be incorrect. The best way to troubleshoot and ensure your manifest points to the correct asset paths is to start an interactive node session in a new terminal window.
First run (in your theme dir):
node
Then run (also in your theme dir):
require('asset-builder')('./assets/manifest.json').globs.js
or (still in your theme dir):
require('asset-builder')('./assets/manifest.json').globs.css
The output will display both the assets' paths and the order they're being included.
If you modify manifest.json while running the gulp watch task it may be necessary to halt the task, run a default gulp build, and then restart your gulp watch task.
If you still have difficulty after viewing the asset-builder output using the steps above then please post (either here or on the Roots forum) the output here along with the installation steps you took when installing the vendor scripts and custom scripts you're attempting to use so that someone can attempt to recreate your environment.

Resources