Inline css from cdn by vue-style-loader - javascript

I want to pass my css class style into html tag in .vue file.
my vue loader setting in webpack.config.js:
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {
css: ExtractTextPlugin.extract({
use: 'css-loader',
fallback: 'vue-style-loader'
})
}
}
},
however, I dont know how to configure the plugin:
plugins: [
new ExtractTextPlugin("https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css")
]
and I even don't know if vue-style-loader could do this for me. Could anybody tell me how to embed my styles (cdn or single css file) into html tag , thanks.

I finally find a solution: I did not use webpack to compile the template. I try to pass the html content to server side (node.js , not necessary, you could do it in client side), and use inline-css to embed the style into related tags. Maybe it's not the best solution, but it does resolve my problem. If anyone gets better anwser , please don't hesitate to tell me.
exports.convertHtmlToDocx = function(req,res){
const HtmlDocx = require('html-docx-js');
const fs = require("fs");
const body = req.body;
let html = req.body.html;
html = `<!DOCTYPE html>
<html>
<head>
<style>
p{color:red;}
</style>
<link rel="stylesheet" href="localhost:3000/stylesheets/bootstrap-3.3.7/dist/css/bootstrap.css"></link>
</head>
<body>${html}</body>
</html>`;
const options = {
url: 'localhost:3000'
}
const inlineCss = require('inline-css');
inlineCss(html, options)
.then(function(html) {
console.log(html)
});
}
client side:
const apiUrl = '';
import axios from 'axios'
api.exportDocx = function(param, callback){
//param: { html: '<div><p>xxxxx</p></div>'} ....
axios.post(`${apiUrl}/convertHtmlToDocx`,param).then(result => {
callback(result)
});
}

Related

How to use function declared in js file that built by webpack in html?

So, what I'm trying to do is, generate a html file called index.html based on template.html, that have styling based on style.css and a function handleClick that declared in index.js. The code below works for the styling, but the handleClick is not working. Is this possbile?
This is my webpack.config.js
const path = require('path')
const HTMLWebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry: {
'page': './src/index.js'
},
output: {
path: path.join(__dirname, '/dist'),
filename: "[name].js"
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: [
'babel-loader'
]
},
{
test: /\.css$/,
use: [
"style-loader",
"css-loader"
]
}
]
},
plugins: [
new HTMLWebpackPlugin({
filename: 'index.html',
template: './src/template.html'
})
]
}
this is my index.js
require('./style.css');
function handleClick(){
alert("called from index")
}
this is my template.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>My Page's Title</title>
</head>
<body>
<div>This background should be blue</div>
<button onclick="handleClick()"> click me </button>
</body>
</html>
and this is my style.css
div {
background-color:blue;
}
The better way is to add addEventListener to that element using your js file. You can do it like this:
<button id="buttonWithFunction"> click me </button>
<script>
// pure js
document.getElementById('buttonWithFunction').addEventListener('click', handleClick);
//with jquery loaded
$('#buttonWithFunction').on('click',function() {
handleClick();
})
You may need to wrap the following in a document.onload for that to work.
Suggest to check namespace of index.js - as i expect, webpack will wrap it in a namespace.
Try to define function on a window namespace.
window.handleClick = () => console.log('Clicked');

Is it possible to import css file conditionally in Vue.js?

I have my admin-panel and pages for clients in one Vue.js project. Is it possible to use certain css-files only if the current route has "forAdmin" meta?
In your mounted() function you can add it like this.
if(someCondition) {
var element = document.createElement("link");
element.setAttribute("rel", "stylesheet");
element.setAttribute("type", "text/css");
element.setAttribute("href", "external.css");
document.getElementsByTagName("head")[0].appendChild(element);
}
By using style-loader with the useable API, you can dynamically apply and remove a stylesheet in your code.
First you'll need to update your webpack config rules so that stylesheets with the .useable.css extension will be loaded with the useable API:
{
test: /\.css$/,
exclude: /\.useable.css$/,
use: [
'style-loader',
'css-loader'
]
},
{
test: /\.useable\.css$/,
use: [
'style-loader/useable',
'css-loader'
]
}
Now in your router code file, you can import your stylesheet and .use() and .unuse() it according to your condition:
import style from './admin.useable.css'
const router = new VueRouter(...)
router.afterEach((to, from) => {
for (const route of to.matched) {
if (route.meta.forAdmin) {
style.use()
}
}
for (const route of from.matched) {
if (route.meta.forAdmin) {
style.unuse()
}
}
})
Make sure you balance the total number of .use() and .unuse() calls correctly because a reference count is maintained behind the scenes to figure out when the stylesheet should be applied.
I'm not sure what your setup is, so there might be a better way of doing what you want though.

how to use TS+css+scss in react SSR framework next?

I'm am using TS + CSS + SCSS in nextJS. I will import some CSS files, but I want to set cssModule:false to those CSS files, then I will import my own SCSS files and set cssModule:true.
The below is my code in next.config.js, it transfers CSS files to module.
const withSass = require("#zeit/next-sass");
const withTypescript = require("#zeit/next-typescript");
const withCSS = require("#zeit/next-css");
module.exports = withTypescript(
withCSS(
withSass({
cssModules: true
})
)
);
Could you please advise me on the right approach of importing CSS files?
The configuration of next-css is global, you either using cssModules or not.
My solution for this was to configure webpack manually to not apply cssModules on files with .global.css suffix.
config.module.rules.forEach(rule => {
if (rule.test.toString().includes('.scss')) {
rule.rules = rule.use.map(useRule => {
if (typeof useRule === 'string') {
return {
loader: useRule,
};
}
if (useRule.loader.startsWith('css-loader')) {
return {
oneOf: [
{
test: /\.global\.scss$/,
loader: useRule.loader,
options: {
...useRule.options,
modules: false,
},
},
{
loader: useRule.loader,
options: useRule.options,
},
],
};
}
return useRule;
});
delete rule.use;
}
});
There is an open PR for next-css to include similar solution to the lib.

how can i get the lang html attribute in webpack configuration

const lang = "the lang html attribute value";
var languages = {
"fr": require("./languages/fr.json"),
"en": require("./languages/en.json")
};
var configuration = Object.keys(languages).map(function(language) {
const loadedLang = (lang.indexOf("fr") > -1) ? "fr" : "en";
return {
name: loadedLang,
entry: './assets/js/main.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'assets/js/dist')
},
plugins: [
new I18nPlugin(
languages[loadedLang]
)
]
}
});
So I am trying to get the <html lang="en-US"> lang attribute and I know that I have no access to the DOM from the webpack config file.
My question is:
Does someone have an idea about how to do this or how to have access to the local storage from webpack?
PS:
I tried a node-localstorage package but it doesn't do the job I want
An answer to your question would be to load the file with the fs api and then use an regex to extract your language:
const fs = require('fs');
const content = fs.readFileSync('PATH_TO_INDEX.HTML', options: { encoding: 'utf8' });
const lang = content.match(/<html lang="(.*)"/)[1];
But I would recommend to do it the "webpack" way:
Create a separate folder for every language, that contains the index.html and the js file specific to each language language.
For this, add the following:
output: {
path: path.resolve(__dirname, `assets/js/dist/${language}/`)
},
plugins: [
new HtmlWebpackPlugin({
template: 'PATH_TO_YOUR_TEMPLATE',
lang: language,
title: 'your page title',
})
]
Please don't forget to install the html-webpack-plugin and require it at the top of your config.
And create a new file index.html with the following content:
<!DOCTYPE html>
<html lang="<%= htmlWebpackPlugin.options.lang %>">
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
</body>
</html>
So now for every language a separate index.html with the right language and the right js file for that language is created in every language folder.
So not the html file dictates the language set, but the webpack config.

How to use Webpack with Google Maps API?

I am using Webpack + html-webpack-plugin to build all my static files. The thing is, when I am using it with Google Maps API, it's not working.
I have this code:
var map;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {lat: -34.397, lng: 150.644},
zoom: 6
});
// the other code, irrelevant
}
And a HTML file:
<!doctype html>
<html>
<head>
</head>
<body>
<div id="map"></div>
<script async="async" defer="defer"
src="https://maps.googleapis.com/maps/api/js?key=<token here>&callback=initMap">
</script>
<script src="script.js"></script>
</body>
</html>
If I run just this file, everything works fine. But if I run this with, webpack it complaints about 'initMap is not a function'. I've looked inside the output, and it seems like initMap is declared not as global function, but as a function inside a module or something like that, so maybe that's the issue.
How should I use Google Maps API with webpack? I know that I can bundle some libs with my script, such as react, should I do the same? What should be the approach here?
UPD: Here is my webpack.config.js:
/* eslint-disable */
const path = require('path')
const fs = require('fs')
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const nodeModules = {}
fs.readdirSync('node_modules')
.filter(function(x) {
return ['.bin'].indexOf(x) === -1
})
.forEach(function(mod) {
nodeModules[mod] = 'commonjs ' + mod
})
const htmlMinifierObj = {
collapseWhitespace: true,
removeComments: true
}
module.exports = [
// the first object compiles backend, I didn't post it since it's unrelated
{
name: 'clientside, output to ./public',
entry: {
script: [path.join(__dirname, 'clientside', 'script.js')]
},
output: {
path: path.join(__dirname, 'public'),
filename: '[name].js'
},
module: {
loaders: [
{
test: /\.js$/,
loader: 'babel',
query: { presets:['es2015', 'stage-0'] }
}
],
},
plugins: [
//new webpack.optimize.UglifyJsPlugin({minimize: true}),
new HtmlWebpackPlugin({
template: 'clientside/index.html',
inject: 'body',
chunks: ['script'],
minify: htmlMinifierObj
})
],
}]
And the output HTML is (I've removed importing script.js from my source file, because it's added by webpack, and turned off the minimization, just for readability):
<!doctype html>
<html>
<head>
</head>
<body>
Login
<div id="map"></div>
<script async defer
src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCGSgj5Ts10UdapzUnWlr34NS5cuoBj7Wg&callback=initMap">
</script>
<script type="text/javascript" src="script.js"></script></body>
</html>
In script.js
After your function declaration, add the function to the global scope, like this:
function initMap() {
// Some stuff
}
window.initMap = initMap;

Categories