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

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.

Related

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

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.

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.

Set Global Styles Without Class Hashing in Nuxt

I have numerous Vue SPAs in a monorepo that all share a common set of global styles, each SPA and the styles are their own package.json workspace. I'm trying to replace one of them with Nuxt.
The global styles are .scss files, they import Vue bootstrap and have some custom variables and classes.
As such, I did a fresh install of Nuxt and then ran:
yarn add -D sass sass-loader#10 fibers
I know I can get global styles like so:
//in nuxt.config.js:
css: [resolve(__dirname+'/../common/styles/index.scss')
Really I thought that should/would be it, and I see it does get injected into the page. However, the class names are hashed, so it doesn't apply to my components.
Instead of this (fake css to test if it goes in the page):
.test{
text-align: test;
top: test;
}
I get this:
.olAmdkaWN_JnK1npjbKiI {
text-align: test;
top: test;
}
How can I stop the global styles from being hashed like this, especially when I may be importing components from the other SPAs/common and their classnames aren't being hashed in the HTML? Only the injected global styles are getting hashed like this.
I've tried various attempts at setting the localIdentName such as:
//in nuxt.config.js
build: {
extend(config) {
config.module.rules.push({
test: /\.scss$/,
use: [{
loader: 'css-loader',
options: {
modules: false
/*
or sometimes I'll try something like:
modules:{
localIdentName: '[local]'
}
*/
}
},
{
loader: 'sass-loader'
}
]
})
},
I've also set:
cssModules: {
localIdentName: '[local]'
},
Again in the nuxt.config.js. But nothing works and furthermore I think I must have a conceptual error about how global styles are meant to work, as I feel like I'm fighting the framework rather than working with it.
My nuxt, webpack and sass-loader verisons are as follows:
nuxt#2.15.4
webpack#4.46.0
sass-loader#10.1.1 (It was at 7.1.x but the console suggested upgrading it - didn't make a difference in terms of solving this)
package.json:
"dependencies": {
"core-js": "^3.9.1",
"common": "1.0.0", (local dependency)
"nuxt": "^2.15.3"
},
"devDependencies": {
"fibers": "^5.0.0",
"sass": "^1.32.11",
"sass-loader": "10"
}
Turns out all I needed was this (the key was to put it in loaders within build):
//in nuxt.config.js
build: {
loaders: {
cssModules: {
localIdentName: '[local]'
},
},
}
Please note this only works if you properly install your dependencies and heed build warnings in regards to css-loader and sass-loader. I tried downgrading sass-loader and this didn't work until I put it back at "10" which is what Nuxt expected (threw a warning).

Dynamically Load CSS with the Angular CLI

I want to be able to dinamically load CSS in my Angular Project.
For that I followed all the steps at this tutorial here:
https://juristr.com/blog/2019/08/dynamically-load-css-angular-cli/
Unfortunately I am stuck at this problem in my angular.json below:
"dyncss": {
...
"build": {
...
options: {
...
"styles": [
"src/styles.scss",
{
"input": "src/client-a-styles.scss",
"bundleName": "client-a",
"inject": false
},
{
"input": "src/client-b-styles.scss",
"bundleName": "client-b",
"inject": false
}
],
}
},
...
},
As soon as I add the line: "inject": false,
I got these errors here:
"Schema validation failed with the following errors: Data path
".styles[1]" should NOT have additional properties(inject). Data path
".styles[1]" should be string. Data path ".styles[1]" should match
exactly one schema in oneOf"
If I remove the line "inject": false ng build work correctly but I have to put inject to be able to load the css dinamically afterwards...
p.s.: Angular version ^9.1.3
Please, any help is really welcome! Thanks in advance!
Try to update your packages properly. Make sure all the packages are up to date. I had similar issues, I forgot to update "ngx-build-plus" to match to my angular project version.

Steps to add Materialize bower package to Sage theme?

I'm trying to add Materialize to this modified sage wordpress theme it is sage with bootstrap removed along with stylus and lostgrid added. [That link is repo without materialize that I'm attempting to add Materialize to.]
I've added these changes yet the materializecss and js don't seem to be available.
"dependencies": {
"materialize": "^0.97.7"
},
"overrides": {
"materialize": {
"main": [
"./css/materialize.css",
"./js/materialize.js"
]
}
}
You can see the commit here. [This is a repo with materialize added to the bower.json.]
What more has to be done to add a bower package to a sage theme or what am I doing wrong?
According to this page / comment the only step required is what I have done in bower.json.
I'm not seeing any Bower libraries added to your bower.json in the repo you linked to, so step 1 is to enter your theme dir and $ bower install materialize --save. Note that I performed this on a fresh install of Sage after I removed all Bower packages and overrides (I also commented all the #import directives in main.scss that come after the wiredep block to safely remove any remnants of Bootstrap's SCSS variables). If you decide to skip to the end of my answer and just use my bower.json file as your own then you'll just need to enter your theme dir and run $ bower install.
After installing Materialize via Bower you should be able to run gulp and see evidence of Materialize, but there are a few issues we need to resolve:
The main property of the Materialize project points to a CSS file and a minified JS file, both of these are not ideal and we will override them.
That first issue above also means when you load your site after running gulp you'll see console 404s because we need to override the fonts too.
This is the final bower.json file I ended up with:
{
"name": "sage",
"homepage": "https://roots.io/sage/",
"authors": [
"Ben Word <ben#benword.com>"
],
"license": "MIT",
"private": true,
"dependencies": {
"materialize": "^0.97.7"
},
"overrides": {
"materialize": {
"main": [
"./dist/js/materialize.js",
"./sass/materialize.scss",
"./fonts/**/*"
]
}
}
}
You will also need to add this to your main.scss file before the wiredep block:
$roboto-font-path: "../fonts/";
The overrides can be improved to use just the individual SCSS components you need instead of all of them. The same goes for the JS source (although the JS files definitely need to be included in a specific order, there are a lot of them and I haven't seen a list anywhere of how they need to be ordered).
EDIT
If you want to include the JS files individually then I've figured out the order, just beware of dependencies if you remove anything and test thoroughly.
{
"name": "sage",
"homepage": "https://roots.io/sage/",
"authors": [
"Ben Word <ben#benword.com>"
],
"license": "MIT",
"private": true,
"dependencies": {
"materialize": "^0.97.7"
},
"overrides": {
"materialize": {
"main": [
"./js/initial.js",
"./js/jquery.easing.1.3.js",
"./js/animation.js",
"./js/velocity.min.js",
"./js/hammer.min.js",
"./js/jquery.hammer.js",
"./js/global.js",
"./js/collapsible.js",
"./js/dropdown.js",
"./js/leanModal.js",
"./js/materialbox.js",
"./js/parallax.js",
"./js/tabs.js",
"./js/tooltip.js",
"./js/waves.js",
"./js/toasts.js",
"./js/sideNav.js",
"./js/scrollspy.js",
"./js/forms.js",
"./js/slider.js",
"./js/cards.js",
"./js/chips.js",
"./js/pushpin.js",
"./js/buttons.js",
"./js/transitions.js",
"./js/scrollFire.js",
"./js/date_picker/picker.js",
"./js/date_picker/picker.date.js",
"./js/character_counter.js",
"./js/carousel.js",
"./sass/materialize.scss",
"./fonts/**/*"
]
}
}
}

Resources