How can I recompile LESS manually in reactjs? - javascript

I have a ReactJs project which uses Webpack and Redux. I am using less for my stylesheets. In this project, I have colors.less file which looks like this -
//colors.less
#color1: red;
....
This file is imported to all the less files who are using this variable.
What I want is change this #color1 variable according to some API data and then the stylesheets should update with the new color. I have access to the this variable in my JS file, but on changing this color I want to reload the stylesheets as well.
Accessing the variable like below -
//utils/less-var-loader.js
const lessToJs = require('less-vars-to-js')
module.exports = function(content) {
return `module.exports = ${JSON.stringify(lessToJs(content))}`
}
//some.js which wants to modify the color
import * as styles from '!!../utils/less-var-loader!./common/colors.less'
styles['#color1'] = blue;

First add the below dependencies for webpack.
Add the less dependencies
webpack.config.js
,{
test: /\.less$/,
loaders: ['style', 'css', 'less']
}
Require it at your entry point.

Related

How to change the src attribute of <img> in .vue files with webpack and vue-loader?

I have a vue.js (version 2.4.4) application built with webpack (version 3.6.0) and vue-loader (version 13.0.5).
In the .vue files, I need to modify the url contained in the src attribute of the <img> tags according to the environment of my application.
In the development environment, the images must come from the
application folder, with a relative path: "/src/images/exemple.png"
In the production environment, the images must come from a cdn, with
an absolute path: "https://my-cdn.net/images/exemple.png"
In the "webpack.config.js" file, I already differentiate the different environments using "process.env.NODE_ENV", like this:
const isDev = process.env.NODE_ENV === 'dev';
But I don't know how to modify the src attribute of the img tags in my .vue files with vue-loader (or with something else).
For information, here is the definition of the vue-loader in the "webpack.config.js" file:
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {
'scss': [
'vue-style-loader',
'css-loader',
'sass-loader'
]
}
}
}
Is there a simple way to do this?
Piggybacking off of #Michael Levy's answer:
I am currently having this issue with Vue 3, #vue/cli 4.5.10, and webpack. I've solved it after much research.
Webpack configurations go into vue.config.js, where there is a lot of abstraction. To fine tune control, you can use chain webpack configs. To help you, use Vue Inspect when you are trying to access specific loaders via chaining.
$ vue inspect > output.js
That will give you a nice list of all the loaders that vue-cli is using.
For example - to modify webpack image options within vue.config.js, you can use vue inspect > output.js, search the output.js file, and discover the loader that's managing images.
Which is: /* config.module.rule('images').use('url-loader') */
To answer the question - in your vue.config.js
module.exports = {
chainWebpack: (config) => {
config.module
.rule("images")
.use("url-loader")
.tap((options) => {
options.name = "images/[name].[ext]";
options.publicPath = isDev ? __webpack_public_path__ : 'https://my-cdn.net/';
return options;
});
},
};
Vue-loader is preconfigured to handle src attributes in Vue single file components as you can see here. So for example <img src="../image.png"> in the template is transformed into:
createElement('img', {
attrs: {
src: require('../image.png') // this is now a module request
}
})
What Webpack do with this require depends on configured loaders. Usual there is a file-loader configured. It looks like this (from project generated by Vue CLI + simplified):
module: {
rules: [
{
test: /\.(png|jpe?g|gif|webp)(\?.*)?$/,
use: [
{
loader: 'file-loader',
options: {
name: 'img/[name].[hash:8].[ext]'
}
}
]
}
]
}
Loader is responsible for copying your file into dist directory and returning public URI, which will be inserted into src attribute.
So what you want can be configured here, by specifying right options. For example:
options: {
name: 'images/[name].[ext]'
publicPath: isDev ? __webpack_public_path__ : 'https://my-cdn.net/'
}
Just take content of dist/images directory after the build and deploy it so it is accessible by https://my-cdn.net/images and it should work....
You can create an alias for/src/images and alter the url at transpile time based on the environment:
{
//..
resolve: {
alias: {
'/src/images': isDev ? '/src/images' : process.env.IMAGE_CDN + '/images'
}
}
}
Another way to handle this would be to use DefinePlugin to create a global variable that each of your images reference.
module.exports = {
chainWebpack: config => {
console.log('\n')
console.log('Setting global variables:')
console.log(`__YOUR_GLOBAL_CONSTANT__: ${JSON.stringify(process.env.YOUR_GLOBAL_CONSTANT)}`)
console.log('\n')
config
.plugin('provide')
.use(require('webpack').DefinePlugin, [{
__YOUR_GLOBAL_CONSTANT__: JSON.stringify(process.env.YOUR_GLOBAL_CONSTANT)
}])
}
}
The example above is utilizing a vue.config.js file, but the strategy should be pretty similar. Also, if you're using something like eslint, you'll need to specify the variable in the globals section as readonly.

Compile template files/stubs into JS variables with Laravel mix

I have a folder /resources/js/stubs. In that folder sits a few files, lets say User.stub, Controller.stub and Migration.stub. I would like to use the content of these files in my javascript by doing something like this
import Templates from './Templates.js'
console.log(Templates.User)
// The content of User.stub is printed
I don't want to use this approach
module.exports = name => `
...
`
I could also use the backend to load the files into the view but I would prefer not to.
So then that requires preprocessing. Can I do it with Laravel mix somehow? If not what are my options, what do I need to add to my Laravel app?
partial solution
Thanks to Diogo Sgrillo for pointing out this solution in the comment.
Install raw-loader
yarn add raw-loader --dev
webpack.mix.js
Add this configuration (In my case all the files will be named with a .stub extension.):
mix.webpackConfig({
module: {
rules: [
{
test: /\.stub$/i,
use: 'raw-loader',
},
],
},
});
Also add a separate pipe in webpack.mix.js like this:
mix.js('src/templates/index.js', 'src/templates.js')
It will compile a list of templates in index.js file and put them in templates.js.
src/templates/index.js
// Dynamically load all stubs using raw-loader (see webpack.mix.js)
let stubs = require.context('./', true, /\.stub$/i);
// Create a object with the filename as key and content as value
exports.stubs = stubs.keys().reduce((result, key) => {
return {
[key.replace(/\.\//,'').replace(/\.stub$/,'')] : stubs(key).default,
...result
}
}, {});
export default { /* dont remove this export default or it will break !?? */}
Later it can be used like this:
let templates = require('./templates.js')
console.log(templates['User.php'])
Please comment or add another answer on how to do this more smooth. What is the difference between exports/export? I cant use import with this method, only require and it breaks if I try to export default (or remove export default.

Render multiple pages unrelated to the main app with Webpack and Mustache

I'm developing a Chrome Extension and I use Webpack to bundle it. I've got my compiled bundle, which is the main part of the app, but I also need an options page to describe the functionality. This options page has nothing to do with the bundle, it's just a static HTML file.
I must put a lot of things in that options page so I want to render that page with Mustache and define all content with JavaScript. For the most part, I've done that.
Here's my Webpack config (I've removed the parts regarding my app):
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
output: {
path: path.join(__dirname, 'extension/build/')
},
plugins: [
new HtmlWebpackPlugin({
template: './src/options/index.html',
inject: false
})
],
module: {
rules: [
{
test: /\.html$/,
loader: 'mustache-loader',
options: {
render: require('./src/options/index.js')
}
}
]
}
}
and in my src/index.js, I have:
require('./options/index.html')
This will open the template and render it with the data in src/options/index.js.
There's a problem with that, however. I run Webpack with webpack --watch and changes to index.js (it holds the template data) do not trigger a rebuild. Also, I would need to go through a lot of trouble to create another static HTML file in the same manner.
It would be ideal if HtmlWebpackPlugin automatically used the template I require() in my entry point so that I don't need to explicitly set it. Also, it would be great if it automatically used a js in that same location to get the data. For example:
require('./options/index.html`)
Renders the template with data from ./options/index.html.js and then emits it. It would be even better if it emitted it to a custom folder specified in the Webpack config.
Is that possible? I couldn't find a plugin/loader that does that.
Edit: I was able to partly fix the rebuild problem by specifying the render option as a function:
{
test: /\.html$/,
loader: 'mustache-loader',
options: {
render () {
var file = './src/options/index.js'
delete require.cache[require.resolve(file)]
return require(file)
}
}
}
But it still doesn't work properly. The rebuild would only trigger after I make changes to index.html. This means that if I change index.js, I need to go and save index.html as well to trigger the build.

vuejs - how to add vue-material theme

I am starting a vuejs project using vue-cli.
I want to use vue-material as the main look and feel but I am not sure how to change the theme color.
from vue-material:
To use custom themes you'll need SCSS/SASS support in your project.
Read more about Pre-Processors. In the near future you'll be able to
use themes with Plain CSS and Stylus too.
and provide with this code:
#import "~vue-material/dist/theme/engine"; // Import the theme engine
#include md-register-theme("default", (
primary: md-get-palette-color(green, A200), // The primary color of your application
accent: md-get-palette-color(pink, 500) // The accent or secondary color
));
#import "~vue-material/dist/theme/all"; // Apply the theme
which I created a style.scss to include them.
and from vuejs come with this code:
module.exports = {
module: {
rules: [
// ... other rules omitted
// this will apply to both plain `.scss` files
// AND `<style lang="scss">` blocks in `.vue` files
{
test: /\.scss$/,
use: [
'vue-style-loader',
'css-loader',
'sass-loader'
]
}
]
},
// plugin omitted
}
First of all, there isn't any webpack.config.js. but there is a babel.config.js. So i created webpack.config.js and include the code too.
When I run npm run serve, nothing seems to happen. there isn't any error or warning too.
I am new with webpack and I really not sure how this all work.
vue-cli doesn't have a webpack.config.js file. You don't need to make one. Instead, you can put your options inside build/webpack.base.conf.js.

Webpack to simply compile a bunch of Pug templates to HTML

Im getting started with webpack but one thing I cannot for the life of me work out is how to take a folder (with possible nested folders), full of .pug templates, and simply compile them to static html and put them in the output folder, maintaining any nested folder structure for each output html file that was in the source templates folder...
I dont want to have to manually specify each individual .pug file, and I definitely dont want webpack to try and parse the .pugs into JS and then attempt to require/import any of the imgs/fonts etc in the pug files and then complain about it, Im just after a basic, static 1:1 compile, pug file in, html file out. Why is it so hard to do that?
Use pug-html-loader to convert .pug to .html file. Use file-loader to copy the file to desired location. Don't use html-loader as you don't want to process resources used by the generated file.
You will end up something like this in your loader rules (untested, webpack 1 syntax, you may need to tweak it for webpack 2)
{
test: /\.pug$/,
loaders: ['file-loader?name=[path][name].html', 'pug-html-loader?pretty&exports=false']
}
Next you need to require all your pug files in your entry file
function requireAll (r) { r.keys().forEach(r); }
requireAll(require.context('./', true, /\.pug$/));
This can be done very simply with only html-webpack-plugin and pug-loader.
webpack.config.js
const HTMLWebpackPlugin = require('html-webpack-plugin');
module.exports = {
// No javascript entrypoint to evaluate. Let the plugin do the heavy lifting
entry: {},
// Translate Pug to HTML
module: { rules: [ { test: /\.pug$/, use: 'pug-loader' } ] },
// Save HTML to file
plugins: [ new HTMLWebpackPlugin({ template: './src/index.pug' }) ]
};
./src/index.pug
doctype html
html(land="en")
head
include path/to/another.pug
...
Got this information from https://extri.co/2017/05/23/using-htmlwebpackplugin-and-pug/ and you can also go further to import css and javascript as normally done with html-webpack-plugin.

Categories

Resources