webpack working with font - javascript

I am trying to use webpack2 with express, and I just can't seem to make my font served, js file works fine, please,help
this is my webpack.config
const devConfig = {
devtool: '#source-map',
entry: [
'./public/js/entry.js',
'webpack/hot/dev-server',
'webpack-hot-middleware/client'
]
,
output: {
filename: './js/main.js',
path: '/',
publicPath: publicPath
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin()
],
module: {
rules: [
{
test: /\.s(a|c)ss$/,
use: [{
loader: "style-loader" // creates style nodes from JS strings
}, {
loader: "css-loader" // translates CSS into CommonJS
}, {
loader: "sass-loader" // compiles Sass to CSS
}]
},
{
test: /\.(ttf|otf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/,
loader: 'file-loader?'
}
]
}
};
and inside my scss file, I have this
src: url('../font-files/firasans-extralightitalic-webfont.woff2') format('woff2'), url('../font-files/firasans-extralightitalic-webfont.woff') format('woff');
}
and my path structure
while I keep getting this error
Module not found: Error: Can't resolve '../font-files/firasans-extralightitalic-webfont.woff2'
can anyone tell me what's wrong...I see some others add there fonts in js file, but I really don't like do it that way

ok, I've struggle another couple hours, now, I find out how to make it work.
the idea is we write relative path in #font-face, but the path is relative to the entry, in my case, the entry is style.sass, so I wrote this
src: url('./font-files/firasans-extralightitalic-webfont.woff2')
now I can resolve this files correctly

Related

How to simply load images with src attribute with webpack 4?

Im stuck and can't get to work my webpack configuration for loading images with src attribute from HTML. I cloned a repo with full setup of webpack, but I know there is a way to simply customize and load images directly from HTML.
Webpack.config.js file:
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
module.exports = {
entry: {
main: "./src/index.js"
},
output: {
path: path.join(__dirname, "../build"),
filename: "[name].bundle.js"
},
mode: "development",
devServer: {
contentBase: path.join(__dirname, "../build"),
compress: true,
port: 3000,
overlay: true
},
devtool: "cheap-module-eval-source-map",
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader" // transpiling our JavaScript files using Babel and webpack
}
},
{
test: /\.(sa|sc|c)ss$/,
use: [
"style-loader", // creates style nodes from JS strings
"css-loader", // translates CSS into CommonJS
"postcss-loader", // Loader for webpack to process CSS with PostCSS
"sass-loader" // compiles Sass to CSS, using Node Sass by default
]
},
{
test: /\.(png|svg|jpe?g|gif)$/,
use: [
{
loader: "file-loader", // This will resolves import/require() on a file into a url
and emits the file into the output directory.
options: {
name: "[name].[ext]",
outputPath: "assets",
}
},
]
},
{
test: /\.html$/,
use: {
loader: "html-loader",
options: {
attrs: ["img:src", ":data-src"],
minimize: true
}
}
}
]
},
plugins: [
// CleanWebpackPlugin will do some clean up/remove folder before build
// In this case, this plugin will remove 'dist' and 'build' folder before re-build again
new CleanWebpackPlugin(),
// The plugin will generate an HTML5 file for you that includes all your webpack bundles
in
the body using script tags
new HtmlWebpackPlugin({
template: "./src/index.html",
filename: "index.html"
}),
Before this project I was able to make that images would simply load from HTML but now ironicly im stuck and can't get this working.
Any help will be very appriciated.
When loading a image directly form HTML, I get the following error:
Error: Child compilation failed:
Module not found: Error: Can't resolve '
./src/assets/images/portret.jpg' in '/home/viktoras/www/sites/painter-new/src':
You can do this:
<img src="<%=require('./src/assets/logo.png')%>">
Plugin Conf
$new HtmlWebpackPlugin({
filename: 'index.html',
template: 'index.html'
}),

How can I use scss files and fonts in Vue project

I created new project with vue-cli and I want to use global scss files in my projects to apply global styles. Also I want to use font-families without importing scss file in every component where I want to use it
I found lots of solutions, but none of them help me. I'm new with webpack, so it is hard to understand what exactly goes wrong.
I install loader npm install sass-loader node-sass --save-dev and try to do lots of things with webpack
webpack.config.js
var path = require('path')
var webpack = require('webpack')
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, './dist'),
publicPath: '/dist/',
filename: 'build.js'
},
module: {
rules: [
{
test: /\.css$/,
use: [
'vue-style-loader',
'css-loader'
],
},
{
test: /\.scss$/,
use: [
'vue-style-loader',
'css-loader',
'sass-loader'
],
},
{
test: /\.sass$/,
use: [
'vue-style-loader',
'css-loader',
'sass-loader?indentedSyntax'
],
},
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {
// Since sass-loader (weirdly) has SCSS as its default parse mode, we map
// the "scss" and "sass" values for the lang attribute to the right configs here.
// other preprocessors should work out of the box, no loader config like this necessary.
'scss': [
'vue-style-loader',
'css-loader',
'sass-loader'
],
'sass': [
'vue-style-loader',
'css-loader',
'sass-loader?indentedSyntax'
]
}
// other vue-loader options go here
}
},
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'file-loader',
options: {
name: '[name].[ext]?[hash]'
}
}
]
},
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js'
},
extensions: ['*', '.js', '.vue', '.json']
},
devServer: {
historyApiFallback: true,
noInfo: true,
overlay: true
},
performance: {
hints: false
},
devtool: '#eval-source-map'
}
if (process.env.NODE_ENV === 'production') {
module.exports.devtool = '#source-map'
// http://vue-loader.vuejs.org/en/workflow/production.html
module.exports.plugins = (module.exports.plugins || []).concat([
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"'
}
}),
new webpack.optimize.UglifyJsPlugin({
sourceMap: true,
compress: {
warnings: false
}
}),
new webpack.LoaderOptionsPlugin({
minimize: true
})
])
}
src/assets/scss/fonts.scss
#font-face {
font-family: "SuisseIntl";
src: url("../fonts/SuisseIntl.woff") format("woff");
}
#font-face {
font-family: "SuisseIntl-Light";
src: url("../fonts/SuisseIntl-Light.woff") format("woff");
}
#font-face {
font-family: "SuisseIntl-SemiBold";
src: url("../fonts/SuisseIntl-SemiBold.woff") format("woff");
}
$body-bg: red;
I want to be able to use font families in style tag inside every component and I want to be able to import scss files to component like this#import '../assets/scss/fonts'; , but now this cause error.
Can someone help me, please? What should I do to make it work?
vue3 (no idea about vue2)
Late but I maybe still a help for someone.
I assume you have a working vue app already. I normaly create mine with vue ui or cli and use typescript. Many things are preconfigured then. Folder structure looks like this:
/node_modules
/public
/src
/assets
/components
/...
/tests
...
package.json
...
create a vue.config.js (if not exists) in the root (where package.json lies) and put this into it:
module.exports = {
css: {
loaderOptions: {
sass: {
// Or wherever your scss files are. I have a "style.scss" which imports all the others
// # in my case points to src/* and is defined in tsconfig.json. Substitute it with src should do fine
prependData: `
#import "#/assets/scss/style.scss";
`,
},
},
},
};
(optional) put your fonts into (if you want them deliver by yourself)
/assets/fonts/
load your fonts in the style.scss (example)
/* local path, dont forget that ~#/ in the url */
#font-face {
font-family : 'Raleway';
font-style : normal;
src : url('~#/assets/fonts/Raleway-VariableFont_wght.ttf') format('truetype-variations')
}
/* or from google fronts */
#import url(http://fonts.googleapis.com/css?family=Roboto+Slab|Open+Sans:400italic,700italic,400,700);
Double check the font path in the scss file. Vue looks into /src folder. So the rootpath for sass-compiler is inside the src folder and the font-url has to start with ~#/assets/fonts/
To use scss in components, make sure you have both sass-loader and node-sass installed as dev dependencies. This will allow you to use scss styling in components with:
<style lang="scss">
</style>
If you want to include some actual styling (something like your fonts that creates actual styling lines in css), create a scss file and include it in your top-most Vue file (by default something like App.vue).
#import "./some/relative/path/to/your/scss/file.scss";
If you want to include variables, functions or mixins in every component without explicitly having to define the import, make a scss file that serves as your entry point for such configuration, e.g. /scss/config.scss. Make sure that you do not output ANY css rules in this file, because these css rules would be duplicated many times for each component. Instead use the file I mentioned before and import your configuration in there as well.
Then, go to your vue.config.js file and add the following to the object:
css: {
loaderOptions: {
sass: {
data: `
#import "#/scss/config.scss";
`
}
}
}
This will automatically load the config file. If you are still using the old structure, you can get the same behaviour by adding a data option to your own sass-loader:
{
test: /\.scss$/,
use: [
'vue-style-loader',
'css-loader',
{
loader: 'sass-loader',
options: {
data: '#import "config";',
includePaths: [
path.join(__dirname, 'src/scss') // Or however else you get to your scss folder
]
}
}
],
},
Here is an example that works for me on the latest version of Vue-CLI (#vue/cli 5.0.0-rc.2, vue3) + TS + dart-sass:
I saved my fonts to the assets folder (src/assets/fonts/public-sans-vf.woff2);
Then I created the _fonts.css file in which I describe the rule for the font (src/assets/scss/_fonts.scss);
#font-face {
font-family: "Public Sans";
src: url("~#/assets/fonts/public-sans-vf.woff2")
format("woff2 supports variations"),
url("~#/assets/fonts/public-sans-vf.woff2") format("woff2-variations");
font-style: normal;
font-weight: 400;
font-display: swap;
}
And then I configure the fonts in vue.config.ts
const { defineConfig } = require('#vue/cli-service');
module.exports = defineConfig({
transpileDependencies: true,
css: {
loaderOptions: {
scss: {
additionalData: `
#import "#/assets/scss/_variables.scss";
#import "#/assets/scss/_fonts.scss";
`,
},
},
},
});

Webpack output bundle larger than expected

The only thing I have in my entry JS file is:
import $ from 'jquery';
The jQuery JS file has the size of 29.5kb from jsdelivr.
My entry, that only includes jQuery, and nothing else, has the size of 86kb.
webpack.config.js
const path = require('path');
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
module.exports = {
entry: './src/js/scripts.js',
output: {
publicPath: "./dist/",
path: path.join(__dirname, "dist/js/"),
filename: "bundle.js"
},
watch: true,
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader",
query: {
presets: [
['env', { loose:true, modules:false }],
'stage-2'
],
plugins: [
['transform-react-jsx', { pragma:'h' }]
]
}
},
{
test: /\.pug$/,
use: [
"file-loader?name=[name].html&outputPath=../dist",
"extract-loader",
"html-loader",
"pug-html-loader"
]
},
{
test: /\.scss$/,
use: ExtractTextPlugin.extract({
use: ['css-loader?url=false', 'sass-loader']
})
},
]
},
resolve: {
alias: {
"TweenMax": path.resolve('node_modules', 'gsap/src/uncompressed/TweenMax.js'),
"TimelineMax": path.resolve('node_modules', 'gsap/src/uncompressed/TimelineMax.js'),
"animation.gsap": path.resolve('node_modules', 'scrollmagic/scrollmagic/uncompressed/plugins/animation.gsap.js'),
}
},
plugins: [
new ExtractTextPlugin('../css/main.css'),
new UglifyJsPlugin({
test: /\.js($|\?)/i
})
],
stats: {
warnings: false
}
};
I should also mention, that going into the output bundle.js it still has the jQuery comments.
jQuery JavaScript Library v3.3.1
https://jquery.com/ ...
Even though I'm calling webpack with the -p argument and have the UglifyJS plugin, but the rest of the file is minified and mangled. Any ideas?
Thanks!
Try to copy and paste minified jquery from your link. It's has size of 86.9 kb.
This link also show that jquery v3 minified file size is also around 80kb.
So you already have correct setup. Maybe your 29.5kb file size is minified+gzipped file.
The 29.5kb file size is definitely the minified+gzipped version as per the link Niyoko posted.
I would also recommend checking out Fuse-Box It brought down our project size from over 1mb to under 200kb (Vendor and App bundles combined). Very easy to get going as well and it is TypeScript first :) It takes the best features from a number of the more popular bundlers and brings them together and builds on those features.

Extracting sass as css using webpack

First. I know questions like this were asked, but I am missing something to understand them. I am trying to compile scss to css. And I would like webpack to basically do the same as sass app.scss : app.css. I tried to configure it using extract-text-webpack-plugin, but I am doing something wrong or missing smth.
It worked if I include(app.scss) in app.js but this makes no sense because if anyone has disabled JavaScript the styles won't work.
This is my webpack.config.js file. I have no idea how to do it.
const webpack = require("webpack");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
var jsConfig = {
entry: "./_dev/scripts/app.js",
output: { filename: "./scripts/bundle.js" },
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader"
}
]
}
};
var scssConfig = {
entry: "./_dev/scss/app.scss",
output: { filename: "./content/app.css" },
module: {
rules: [
{
test: /\.scss$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: "css-loader"
})
}
]
},
plugins: [
new ExtractTextPlugin({filename:"./_dev/scss/app.scss"}),
]
};
var config = [scssConfig, jsConfig];
module.exports = config;
Edit: I also found this. This series would have helped with all my questions so if you have similar questions make sure to read it before asking!
https://codeburst.io/simple-beginner-guide-for-webpack-2-0-from-scratch-part-v-495dba627718
You need to include your app.scss for webpack to be able to find your scss references because webpack will traverse your project and apply loaders to all files it can find through references starting from app.js recursively down. If you don't have references to app.scss somewhere in the project webpack can't find it and it won't build it. So in the entry of you project (assume it is app.js) you need to do this:
import 'relative/path/to/styles/app.scss';
But it doesn't mean that those who don't have js enabled won't receive your styles. You need to include app.scss only for the build phase of your project, after that your styles will be included in html and will be loaded even for those without js enabled.
webpack concepts section explains how webpack finds dependencies based on your entry point building its internal graph of dependencies.
Update:
There is a way that allows you to not add your app.scss in your js. You can include multiple files in your entry object in your webpack config. Here is an example of how configuration might look in your case:
const webpack = require("webpack");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
var config = {
entry: {
main: [
"./_dev/scripts/app.js",
"./_dev/scss/app.scss"
],
},
output: {
path: './scripts',
filename: "bundle.js"
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader"
},
{
test: /\.(css|scss)/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: ['css-loader', 'sass-loader']
})
}
]
},
plugins: [
new ExtractTextPlugin("./_dev/scss/app.scss"),
]
};
module.exports = config;
More information available on SO question webpack-multiple-entry-points-sass-and-js.
You also have incorrect configuration of ExtractTextPlugin in webpack. You are placing the whole path in the option for filename, which is not correct. In your case it should look like this:
plugins: [
new ExtractTextPlugin("./_dev/scss/app.css"),
]

Webpack and Angular HTML image loading

I have been breaking my head with webpack and angular. This might have a simple answer but I cant figure it out. I have read almost every answer here in stack overflow on this topic to no avail.
I have an html page like this (also other template that have images):
<body>
<img ng-src="../images/angular-webpack.png">
<md-button class="md-primary md-raised">
Button
</md-button>
</body>
I also have a webpack config:
var webpack = require('webpack');
var CopyWebpackPlugin = require('copy-webpack-plugin');
var path = require('path');
module.exports = {
context: path.resolve(__dirname + '/src'),
entry: ['./js/core/app.module.js'],
output: {
path: './release',
publicPath:'/',
filename: 'app.js'
},
module: {
loaders: [
{
test: /\.html/,
exclude: 'node_modules',
loader: 'raw-loader'
},
{
test: /\.css/,
exclude: 'node_modules',
loader: 'style-loader!css-loader'
},
{
test: /\.(jpe?g|png)$/i,
exclude: 'node_modules',
loader: 'url-loader?limit=8192!img'
}
]
},
plugins: [
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
}),
new CopyWebpackPlugin([
{from: './index.html', to: './index.html'}
], {
ignore: [
'*.txt',
{glob: '**/*', dot: true}
]
})
],
devServer: {
contentBase: './release'
},
watch: true
};
...but i do not see my images loading. I have tried url-loader, file-loader with publicPath and without it. I am confused, I do not know how to format the webpack config or the html image tag for it to work.
Anyone has any experience on getting images to work with webpack? Also I do not want to include my images in the controllers or any other js file. I want the images to be declared in the html page.
The raw-loader is supposed to turn a text file into a CommonJS module that exports the file contents as a string – nothing more.
If you want webpack to recognize the file as HTML and all its references in it, you need the html-loader. The html-loader parses the given file with an HTML parser and picks up references to other files within attributes. By default, that is only <img src="...">. In your case, you need to tell the html-loader to also look for ng-src attributes, like this:
// webpack.config.js
...
loaders: [{
test: /\.html$/,
loaders: [
"html?" + JSON.stringify({
attrs: ["img:src", "img:ng-src"]
})
]}
]

Categories