Is there a way to minify css classNames? - node.js

I wanna make some obfuscation and minification by changing my css class-names. As I don't think this is a right way to minify it by myself, so I'm using css modules with
getLocalIdent: MinimalClassnameGenerator({ length: 1 })
//where MinimalClassnameGenerator is webpack-minimal-classnames
and it works at css side, class names is minified. But unfortunately at output.bundle.js I've found lines like this
const N = { class: "super-puper-class" },
[
"__cssModules",
{
$style: {
"super-puper-class": "J",
It means that only css side is minified and somebody could know real class name after compilation. Is there a way to minify and obfuscate classNames right?

Related

Webpack image loader with dynamic inline background images via CSS?

I'm using webpack with react, and I usually import and use my images as such:
import CalNotices from 'assets/img/calendar-notices.png';
<img className='img-center' role='presentation' src={CalNotices}/>
that works fine, and when I do production build, those images area neatly put into appropriate folders.
However, at times, I want to use images for backgrounds, and use it as such:
const divStyle = {
backgroundImage: `url(${item.logo})`,
backgroundSize: 'contain',
backgroundRepeat: 'no-repeat',
backgroundPosition: 'center'
}
<div className='image-holder' style={divStyle}></div>
with item.logo being an absolute path to the image.
This works fine in dev, but when I do a prod build, those images are obviously missing, since they didn't get picked up by the webpack image loader. How should I approach this?
my image loader config is
{
test: /\.(jpg|png|gif|eot|svg|ttf|woff|woff2)(\?.*)?$/,
include: [paths.appSrc, paths.appNodeModules],
loader: 'file',
query: {
name: 'static/media/[name].[ext]'
}
},
Based on your comments (all of the images are in /src/assets/img/logos), you can leverage webpack's require.context functionality to bundle the entire logo folder at build time:
// causes webpack to find and bundle *all* files in logos or one of its subfolders.
const logoContext = require.context("assets/img/logos", true, /\.(png|jpg)$/);
// later...in your render() method
// assumes item.logo is a path relative to the logos folder
// example: "credit-card-xxx.jpg" or "./credit-card-xxx.jpg"
const logoUrl = logoContext.resolve(item.logo);

Use different loader in Webpack depending on from where I'm importing

I'm using the svg loader to import SVG icons in my React file.
webpack.config.js:
{ test: /\.svg(\?.*)?$/, loader: 'svg' }
component.js:
import Icon from './icon.svg'
render () {
return <svg {...Icon.attributes} dangerouslySetInnerHTML={{ __html: Icon.content }} />
}
So far I have no issues. I also want to use SVG images in my CSS. If I do this:
.class {
background-image: url('./icon.svg');
}
My final result looks like this:
I would like to use the url loader for my CSS file. I tried this:
.class {
url('url!./icon.svg?name=[path][name].[ext]&limit=1&mimetype=image/svg+xml');
}
In my CSS I get:
This looks like what I want but the image is not displayed and if I open the url in a separate tab I get this:
Which leads me to think that the svg loader is still running.
Is there a way to specify a different loader based on from which file I'm importing?
Add issuer see: webpack.js.org/configuration/module/#rule-issuer
An example:
{
test: /\.svg(\?.*)?$/,
issuer: /\.js$/,
loader: 'svg-inline-loader',
},
{
test: /\.svg/,
issuer: /\.scss$/,
use: {
loader: 'svg-url-loader',
options: {},
},
},
I'm not sure that's exactly what you need; it sounds like you need to trigger webpack's module resolution. By default, the CSS loader treats image URL references as relative (like they would normally be w/CSS). You need to prefix the URL with a '~' to tell it to use webpack's require resolution to find the module.

SVG.js plugins and RequireJS

I am trying to write an SVG.js plugin to create some dynamic graphics. The site I want to use it in uses requireJS via django-require.
I am struggling to get the plugins to augment the SVG object, exported by SVG.js, properly.
The plugin is modelled after svg.path.js, another SVG.js plugin, and looks something like this:
(function() {
SVG.extend(SVG.Path, {
myGraphicType: function(p){
return this;
}
});
}).call(this);
My plugin will depend on svg.path and svg. svg.path also depends on svg. The shim entry in the requireJS config looks like:
shim: {
'svg-0.32' : {
exports: 'SVG'
},
'svg.path': {
deps: ['svg-0.32']
},
'svg.myplugin': { //My plugin!
deps: ['svg-0.32', 'svg.path']
}
}
The main app is defined() to depend on both svg and svg.myplugin. However, when I come to use the plugin like this:
var myGraphic = SVG.path().myGraphicType()
I am told that SVG is not defined in the svg.myplugin.js file.
What is the right way to include plugins like this using requireJS?

Susy (Responsive grids for Compass) text direction

The Susy grid has a $from-direction variable, but I can't use it like so:
[dir="rtl"] {$from-direction: right;}
The generated CSS changes all direction related Susy CSS to right-to-left and is not prepended with [dir="rtl"].
What am I doing wrong?
Unfortunately there is no way for Sass (or Susy) to know anything about your HTML. Because things are pre-compiled, you have to nest the actual styles inside your switch, not just the variable setting. That probably means two different compiled stylesheets, which you can do easily in Sass, using that setting.
You'll need two scss files, e.g. rtl.scss and ltr.scss. Each one starts with that variable, and then imports all the necessary partials for your site:
// rtl.scss
$from-direction: right;
#import "my-site-partials.scss";
and
// ltr.scss
$from-direction: left;
#import "my-site-partials.scss";
Then you just need to load the correct css output file in your HTML depending on the direction. You can also do it in a single file, but you'll be loading twice the code you use in either case, and nesting all your styles an extra level. I recommend the two-file approach.
UPDATE: A Single-file approach.
You can use the same technique in a single file, but it will require an extra wrapper around all your styles. Something like this:
#each $dir in ltr, rtl {
$from-direction: if(ltr, left, right);
[dir="#{$dir}"] {
// your styles
}
}
You could make that into a mixin:
#mixin bi {
#each $dir in ltr, rtl {
$from-direction: if(ltr, left, right);
[dir="#{$dir}"] {
#content;
}
}
}
#include bi {
// your styles
}
Or you could override only specific styles that change with direction:
#mixin rtl {
$from-direction: right;
[dir="rtl"] {
#content;
}
$from-direction: left;
}
// your ltr styles
#include rtl {
// your rtl overrides
}
There are many other variations on that, and features you could add for flexibility. But this should get you started.

Node.js, Express, Jade - Separate layout files

I'm working on some project with Node.js, Express and Jade, where I'd like to seperate layout files. Inside the main file is already separated header, but I don't know how to do this for sublayout where I need to pass data. In this case I need to pass data to widgets for every view on page, but in the route would be too many things to load data into widgets instead of some easy solution which I'm looking for.
I could do this thing on the way which I described above - to load data in view with every request, but this is somehow time & cpu consuming.
Another way I'm thinking of is to create some sublayout for widgets in which I'd load data once and then would be available all the time without calling data from DB in all requests. What's the best way to do that?
I work with mustache but I think you can use a similar strategy that I do.In most of the mustache templates that I use there is a common header and footer section.Along with the scripts and css files.I have created a separate partials file that exports these partials
.For instance my partial file looks like this.
exports.partials = function (isAuthenticated)
{
var menu;
isAuthenticated ?
menu = {
header: '',
footer: ' '
} :
menu = {
header: '',
footer: ''
}
return menu;
};
exports.staticResources = {
bootstrap :'//netdna.bootstrapcdn.com/twitter-bootstrap/2.2.2/css/bootstrap-combined.min.css',
fonts : '//netdna.bootstrapcdn.com/font-awesome/3.0/css/font-awesome.css',
jquery : '//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js'
};
I have another method called generatePartials which as the name suggest generate the partials for my templates
exports.generatePartials = function(isAuthenticated){
var menu = resources.partials(isAuthenticated);
var partials = {
header : menu.header,
footer : menu.footer,
bootstrap : resources.staticResources.bootstrap,
fonts :resources.staticResources.fonts,
jquery :resources.staticResources.jquery,
};
return partials;
};
Now while rendering the template all I have to do is this
app.get('/routeName',function (req, res){
var partials = require('../helpers').generatePartials(req.isAuthenticated());
return res.render('viewName.html', partials);
};
And that's it.

Resources