How to resize images for different responsive views? - image-resizing

I created a site with nuxt.js and bootstrap. For the responsive views i need to create different image sizes. Nuxt.js can't resize images. How do you do this?

Now I have the solution. Install responsive-loader and sharp.
Modify the nuxt.config.js and add the code under build: {}:
build: {
/*
** Run ESLint on save
*/
extend (config, { isDev, isClient }) {
// Default block
if (isDev && isClient) {
config.module.rules.push({
enforce: 'pre',
test: /\.(js|vue)$/,
loader: 'eslint-loader',
exclude: /(node_modules)/
})
}
// Default block end
// here I tell webpack not to include jpgs and pngs
// as base64 as an inline image
config.module.rules.find(
rule => rule.loader === "url-loader"
).exclude = /\.(jpe?g|png)$/;
// now i configure the responsive-loader
config.module.rules.push({
test: /\.(jpe?g|png)$/i,
loader: 'responsive-loader',
options: {
min: 575,
max: 1140,
steps: 7,
placeholder: false,
quality: 60,
adapter: require("responsive-loader/sharp")
}
})
}
}
Now you can use the following code to display images
<img :src="require('~/assets/images/Foo.jpg?size=400')" :srcset="require('~/assets/images/Foo.jpg').srcSet">

If you don't want to rely on webpack for responsively loading images, you may want to try this nuxt module: https://github.com/reallifedigital/nuxt-image-loader-module
The downside to this module is that it doesn't currently support srcset natively and requires a local installation of the Graphicsmagick library. The upside is that anything that's available in Graphicsmagick (image manipulation wise) can be used to process your images. Also, you can implement your own image srcset from following the instructions and implementing your image tag like this:
<img src="image.png" srcset="image-1x.png?style=1x 1x, image-2x.png?style=2x 2x alt="" />
You should be able to implement any responsive image this way.
For our responsive views in nuxt, such as a 'feed' of latest content, we wanted to use smaller images from what was being used on the main articles, so this module does exactly what we need it to.
Disclosure: I wrote this module to solve our particular responsive requirement which, given the original poster's description, sounds like there's a lot of overlap.

It's not a task for Nuxt, but for Webpack.
You have to install a webpack loader to resize your images on build task and that will inject the srcSet in your html generated from Nuxt.js
eg. responsive-loader https://github.com/herrstucki/responsive-loader
About Nuxt.js & webpack configuration: https://nuxtjs.org/faq/extend-webpack

Related

Is there a way to render Loopback 4 "/explorer" in collapsed mode by default

I have installed Loopback 4, and mounted my legacy Loopback 3 app into it as part of my migration - all good so far.
However my (swagger-ui shaped) explorer renders expanded by default - and there are a LOT of endpoints and services - making it very hard to find what I'm looking for.
My instinct tells me I should be able to add a configuration here in my application.ts - but I cannot find anything.
this.configure(RestExplorerBindings.COMPONENT).to({
path: '/explorer',
docExpansion:'none' <<<<< this is what I would expect/like
});
this.component(RestExplorerComponent);
Has anyone been able to accomplish this? It seems from the forums there are a lot of requests for something like this.
You could try this.
https://www.npmjs.com/package/#loopback/rest-explorer
Overriding the Swagger UI index.html
For more flexibility, the indexTemplatePath property can be used to allow full customization of Swagger UI configuration options.
indexTemplatePath should be an absolute path to a html.ejs template.
To get started, download the default index.html.ejs,
add /explorer/index.html.ejs to your project, and update the configuration:
this.configure(RestExplorerBindings.COMPONENT).to({
// For example, create a directory "explorer" at the same level
// as "src" and "node_modules" in your applciation structure
indexTemplatePath: path.resolve(__dirname, '../explorer/index.html.ejs'),
});
you can then add
docExpansion: 'none',
inside the index.html.ejs file.
const ui = SwaggerUIBundle({
url: '<%- openApiSpecUrl %>',
dom_id: '#swagger-ui',
deepLinking: true,
filter: true,
docExpansion: 'none',
defaultModelsExpandDepth: 0,
defaultModelExpandDepth: 0,
presets: [
SwaggerUIBundle.presets.apis,
// SwaggerUIStandalonePreset
SwaggerUIStandalonePreset.slice(1) // Disable the top bar
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
layout: 'StandaloneLayout'
})

PIXI Sprite displays in black

I am trying to set a Sprite as a background in my viewport. The grid.png is 23040 x 9984 pixels.
this.app.loader
.add("grid", require("./assets/grid.png"))
.load((loader, resources) => {
const grid = new PIXI.Sprite(resources.grid.texture);
grid.anchor.set(0, 0);
grid.scale.set(1);
this.container.addChild(grid);
});
The Sprite shows in my Container but only in black. If I try with a smaller png (25 x 25 pixels) it works.
I also made sure my viewport world width and height were big enough :
this.viewport = new Viewport({
screenWidth: 953,
screenHeight: 409,
worldWidth: 25000,
worldHeight: 10000,
interaction: this.app.renderer.plugins.interaction
});
Here is the sandbox code
https://codesandbox.io/s/pixi-sprite-loading-cn7re?file=/src/App.vue:572-875
You see sprite as black (in chrome) because is too big and you add it using "require":
.add("grid", require("./assets/grid.png"))
this does basically following:
.add("grid", "data:image/png;base64,iVBORwA<MoreBase64StringHere>")
which is too much for browser when grid.png has such big dimensions.
You should add it by passing url to the image - instead of requiring whole inlined image:
.add({
name: "grid",
url: "grid-small.png",
crossOrigin: "anonymous"
})
Note that grid-small.png should be in "public" dir of codesandbox, and crossOrigin: "anonymous" is to avoid problems with cross-origin when image is loaded.
Such big images (especially if it consist basically many copies of same image) should be avoided. You should try using for example some small/medium chunk of the image (the mentioned grid-small.png) and TilingSprite technique. In such way you can easily have 25000 x 10000 grid - as you can see in codesandbox below.
You shouldnt keep Pixi objects inside Vue component state - i already told you in other post about it ( https://stackoverflow.com/a/62094101/3174731 ) - you are not listening ;) . Why do you want Vue to analyze Pixi objects? Is not its job. Vue should be about what is going on in DOM etc - not about whats in canvas. See codesandbox linked below how much faster everything is if you keep Pixi related objects outside of Vue component (myPixi variable).
You can see how above optimizations work in following codesandbox (modified version of yours) : https://codesandbox.io/s/pixi-sprite-loading-3vsne?file=/src/App.vue

Styled-Components how to minify css in SSR?

Using styled-components in React project with SSR. When the page loads more than half of the page weight consuming by styled components. Is there any way to improve this? Is it possible to minify generated styles ?
[
'babel-plugin-styled-components',
{
ssr: true,
displayName: false,
fileName: false,
}
]
You can pass this in your .babelrc config.
Good documentation here - https://styled-components.com/docs/tooling#minification
Although I am searching for a way to custom minify my classes. Anybody with any leads on that, please let me know.

Using 3rd party jquery plugins in Apostrophe cms

In my Apostrophe cms I have a portion in the header like this (in the outerLayout.html file):
<div id="sticky-header">
...
</div>
In the footer I have done the following:
<script src="/thirdparty/jquery/jquery-3.2.1.min.js"></script>
<script src="/thirdparty/sticky/jquery.sticky.js"></script>
I understand that apostrophe somehow includes jQuery, but if I do not include it myself I get an error in the console:
jquery.sticky.js:22 Uncaught ReferenceError: jQuery is not defined
at jquery.sticky.js:22
at jquery.sticky.js:24
I also have the following in one of the always.js files
$("#sticky-header").sticky({
topSpacing:0,
zIndex:1000
});
And that generates the error:
always.js:109 Uncaught TypeError: $(...).sticky is not a function
at always.js:109
How can I solve this?
In your case, the reason you need to push your own copy of jQuery is that including files from outerLayout is running front-end javascript OUTSIDE of Apostrophe's front-end asset pipeline.
To include your 3rd party / custom javascript INSIDE Apostrophe's asset pipeline (which is recommended and where jQuery is initially run) you need to push the javascript files from an Apostrophe module.
The quickest path forward is to push the asset from the apostrophe-assets module which should already be in your project.
in app.js
...
'apostrophe-assets': {
scripts: [
{
name: 'yourFile'
}
]
},
...
This will load lib/modules/apostrophe-assets/public/js/yourFile.js
More on pushing assets to the browser here http://apostrophecms.org/docs/tutorials/getting-started/pushing-assets.html
Down the road you may want to organize front-end assets by their appropriate module instead of pushing them all in a heap, this would be a good reference
http://apostrophecms.org/docs/tutorials/getting-started/custom-widgets.html#adding-a-java-script-widget-player-on-the-browser-side
Also, what you can expect to be there when you do push javascript
http://apostrophecms.org/docs/tutorials/getting-started/custom-widgets.html#what-39-s-available-in-the-browser
Thanx a lot Stuart - that definitely pushed me in the right direction :)
However what I ended up doing to make it work was to first put the files in lib/modules/apostrophe-assets/public/js/ like you suggested, and then edit the lib/modules/apostrophe-assets/index.js file:
module.exports = {
stylesheets: [
{
name: 'site'
}
],
scripts: [
{
name: 'bootstrap/js/bootstrap.min'
},
{
name: 'sticky/jquery.sticky'
},
{
name: 'scrollto/jquery.scrollTo.min'
}
]
};

using EJS with requirejs

I had a problem include ejs into requirejs. I put <script data-main="js/app" src="js/require.js"></script> in my and inside of body create EJS object.
In my app.js,
require.config({
paths: {
//library
jquery: 'lib/jquery-1.11.1.min',
jquerymobile: "lib/jquery.mobile-1.4.2.min",
text: 'text',
ejs: 'ejs_0.9_alpha_1_production'
},
shim: {
"ejs": {
exports: 'ejs'
}
}
});
require(['jquery', 'jquerymobile','text','ejs'], function ($, mobile) {
console.log('jQuery version:', $.fn.jquery); // 1.9.0
});
when it is running, it throws EJS is not defined error. However, if I include
<script type="text/javascript" src="js/ejs_0.9_alpha_1_production.js"></script>
in the head, everything goes well.
Regards
Hammer
Lately I just get through similar trouble using ejs from the browser. I post the answer as it could save somebody's time.
I suggest you double check your ejs library is indeed coming from https://github.com/visionmedia/ejs. There is quite some tuned version of ejs around right now because it is becoming very popular. Unfortunatly most of thoses versions target specific needs and return different object to the window (eg. EJS instead of ejs) or don't even return anything usefull for requirejs.
=> In both case this would expalin why your shim exports return undefined.
Once you get it to load properly, let me also spot on an awesome requirejs-ejs plugin at https://github.com/whitcomb/requirejs-ejs . It could help you preload and render your template in a nice requirejs way.

Resources