Build prod don’t display font - basic webpack init - css

I need to use font named ‘myFontName’ from ttf file in production environment after launch this command :
npm run build
For this test, i have only initialize project with this command :
vue init webpack myProjectName
In dev environment (npm run dev) i can display and use my font. But i can’t see the same font after build. However, in the production environment i can see my font in css rules (browser console).
So, font seems to be display in dev and not in production.
This is my tree project:
src
|_assets
|_components
|componentfile.vue
|_fonts
|_myFontFile.ttf
This is my dist folder tree :
dist
|_js
|_static
|_fonts
|_myFontFile.ttf
I call my font directly in my component.vue file :
<script scoped>
#font-face{
font-family:"myFontName";
src: url("./fonts/myFontFile.ttf") format("truetype");
}
<script>
Webpack is nativ from init. I have this loader in my webpack.base.conf.js :
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
}
For build config :
build{
build.assetsPublicPath: ‘/’
}
So, what's wrong ? Why prod env don't display my font correctly ?
Thanks to help me to resolve this font problem.

Okay no response ? Nobody...
Finally, here is my solution.
In util.js file, insert :
publicPath: '../../'
In this part of code
// Extract CSS when that option is specified
// (which is the case during production build)
if (options.extract) {
return ExtractTextPlugin.extract({
use: loaders,
fallback: 'vue-style-loader',
publicPath: '../../'
})
} else {
return ['vue-style-loader'].concat(loaders)
}
But why ?
Check this two similar issues..
Vuejs forum similar issue
Github similar issue
After build, i can inspect style CSS files in
/dist/src/static/css/
... and noted that my #font-face source have the wrong path after build according to ma dist tree folder :
#font-face{font-family:myFontFileBis;src:url(static/fonts/myFontFileBis.ttf) format("truetype")}
Instead of url(static/fonts/myFontFileBis.ttf), i need to get url(../../static/fonts/myFontFileBis.ttf).
So, i need to set publicPath in util.js.
it work now !

Related

My css file is too big because url-loader is inserting a .jpg code into the .css file - How can I config webpack so it points towards the img?

I'm finishing an online course about some web dev tools.
In the course, somehow, the instructor doesn't run into a problem with webpack while using a .jpg url in the .css. After searching on StackOverflow and Google I've managed to find the answer in using the url-loader webpack plugin.
This worked fine while I was running a local dev environment.
However, when I built the website for deployment, the .css file was sized in 200kb. After running the file through a beautifier, I've found that it was because of the .jpg code being injected into the .css. After deleting that portion, the file size dropped down to less than 16kb.
How can I configure my webpack so when it builds, it replaces the inserted .jpg to a url pointing towards the actual image file?
Here are:
The repo: https://github.com/sethalberdier/fictional-travel-site
The folder containing the huge css file (and also the one that is live): https://github.com/sethalberdier/fictional-travel-site/tree/master/docs
The code bits that matter, imo:
css:
#mixin atLarge {
background: url('/app/assets/images/testimonials-bg.jpg') top center;
}
inside webpack.config I have this rule for the exports module:
{
test: /\.(png|jpg)$/,
loader: 'url-loader',
},
As per url-loader docs, it seems like you need to specify a limit in your webpack config file. For instance:
{
loader: 'url-loader',
options: {
limit: 8192
}
}
If you want url-loader to never transform images into base64 strings, specify {limit: false} or use file-loader instead.

CSS/SCSS Code module not found in VSCode using relative path

I'm writing a SharePoint Framework web-part in VS Code.
Unfortunately my scss styles file cannot be found, even though it's in the same path - please see the image below:
I also checked the styles file Events.module.scss in case an error in their was preventing it being imported, but there are no issues with that file...
I have tried restarting VS Code...tried moving the files around, tried renaming the scss file...
So what is missing here, and how can I resolve it?
I found the solution at How to use CSS Modules with TypeScript and webpack
Either we can bypass the import by using const s = require('./Button.css');
or, install Typings for CSS Modules like so:
npm install --save-dev typings-for-css-modules-loader
then add the new rule to webpack.config:
module: {
rules: [
{
test: /\.css$/,
include: path.join(__dirname, 'src/components'),
use: [
'style-loader',
{
loader: 'typings-for-css-modules-loader',
options: {
modules: true,
namedExport: true
}
}
]
}
]
}
it's a bit of a faff or kerfuffle but it is possible

Ionic3 : the best way to import css from node_modules

I am trying to import the .css from full-calendar package.
First, I created a new component my-calendar (html, scss, ts).
Then, I tried 3 different ways but only the last one worked for me:
Reference the file directly, as the documentation suggested, in the index.html (it does not work because the reference to node_modules is lost when you build the project)
<link href="node_modules/fullcalendar/dist/fullcalendar.min.css" rel="stylesheet">
Adding #import "~fullcalendar/dist/fullcalendar.min.css"; in my-calendar.scss. If I am not wrong, this should add the style into main.css when the project is being built (is not working)
Create custom copy config (copy.config.js)
module.exports = {
...
copyFullCalendar: {
src: ['{{ROOT}}/node_modules/fullcalendar/dist/fullcalendar.min.css'],
dest: '{{BUILD}}'
}
}
and adding #import "fullcalendar.min.css"; into my-calendar.scss
UPDATE:
and adding #import "fullcalendar"; into my-calendar.scss
to avoid compiler errors when use ionic build --aot --minifycss --minifyjs
I would appreciate if someone could clarify the best way and explain if I misunderstood some concept.
PS: Remember that I am working with Ionic3 and I am not using the Angular CLI.
third method of yours will be the best way to implement , but it can be done in another way more like ionic.
You need to make use of the includePaths when configuring the custom path , as we are dealing with custom css, add sass.config.js to local project folder where we configure custom includePaths like this
includePaths: [
....
'node_modules/ap-angular2-fullcalendar'
],
In package.json scripts to include custom css configuration file, like this:
"scripts": {
.....
"ionic:serve": "ionic-app-scripts serve -s ./config/sass.config.js"
},
Only problem with this implementation is when you update ionic-app-scripts you have to compare the native sass.config.js file to the local file and check if there is anything changed.
This is a troublesome method and an issue was raised in Github but unfortunately they closed the issue with the following justification
Configs are extended, so only include the fields that you're changing.
Everything else will inherit the defaults.
As of #ionic/app-scripts : 3.2.0, it seems you'll still need to
#include FILE; somewhere
See this closed issue on app script's github
I found that as of
'Ionic Framework : ionic-angular 3.9.2'
you have two choices insert your import in src/theme/variables.scss or src/app/app.scss.
For example in variables.scss
/* some declarations here */
#import 'insrctest';/*file sits in src/test/insrctest.scss*/
And in my custom.config.js
includePaths: [
'node_modules/ionic-angular/themes',
'node_modules/ionicons/dist/scss',
'node_modules/ionic-angular/fonts',
'./src/test', /* when the import above gets called, node-sass will look in here */

Webpack and Sass correctly processes background: url() image but then it's not found when used with webpack-dev-server

I am using Webpack 2 and webpack-dev-server together with Sass loader, actual configuration:
{
test: /\.scss/,
loaders: [
"style",
{ loader: "css", query: { modules: false, sourceMap: true } },
{ loader: "resolve-url" },
{ loader: "sass", query: { sourceMap: true } }
]
}
This works quite well and the image referenced in background: url() is processed by webpack and also replaced in the style for something like background-somehash.jpg, this file can be accessed by typing http://localhost:8080/background-somehash.jpg. It also works when I provide whole url (including localhost) in a style background definition using developer tools...
The only thing that don't work is the original css produced by webpack which looks like background: url(background-somehash.jpg). I also tried various urls like ./, ../, ../../ or ./images/ to try out if root was set somehow differently. What I don't get is that the file is readily available at the root...
EDIT:
When used together with extract-text-webpack-plugin which extracts styles into separate real styles.css file it works just fine. The question is why it doesn't work when final css is being served from javascript bundle ?
CLARIFICATION:
Everything is referenced correctly, the image is available, it all works when I extract css into separate file using extract-text-webpack-plugin it just doesn't work when the completely same css is served from bundle.js which is then referenced in the index.html like <link href="blob:..." rel="stylesheet">
Things you should check:
Is the referenced image recognized by webpack?
Just delete the image and check if the webpack build fails. If that's the case, it is not an issue with your loader configuration.
Check the requested URL with your browser developer tools
If the request is terminated with a 404:
Check if output.publicPath (webpack) / contentBase (webpack-dev-server) point to the same location. This is from the browser's perspective (=no absolute file paths)
If you're using a <base>-tag, you need to ensure that it does replace the base URL correctly.

Webpack "OTS parsing error" loading fonts

My webpack config specifies that fonts should be loaded using url-loader, and when I try to view the page using Chrome I get the following error:
OTS parsing error: invalid version tag
Failed to decode downloaded font: [My local URL]
The relevant parts of my config look like this:
{
module: {
loaders: [
// ...
{
test: /\.scss$/,
loaders: ['style', 'css?sourceMap', 'autoprefixer', 'sass?sourceMap'],
},
{
test: /images\/.*\.(png|jpg|svg|gif)$/,
loader: 'url-loader?limit=10000&name="[name]-[hash].[ext]"',
},
{
test: /fonts\/.*\.(woff|woff2|eot|ttf|svg)$/,
loader: 'file-loader?name="[name]-[hash].[ext]"',
}
],
},
}
It doesn't happen in Safari, and I haven't tried Firefox.
In development I'm serving files through webpack-dev-server, in production they're written to disk and copied to S3; in both cases I get the same behaviour in Chrome.
This also happens to larger images (greater than the 10kB limit in the image loader config).
TL;DR Use absolute paths to your assets (including your complete hostname) by setting your output.publicPath to e.g. "http://example.com/assets/".
The problem
The problem is the way that URLs are resolved by Chrome when they're parsed from a dynamically loaded CSS blob.
When you load the page, the browser loads your Webpack bundle entry JavaScript file, which (when you're using the style-loader) also contains a Base64 encoded copy of your CSS, which gets loaded into the page.
This is what it looks like in Chrome DevTools
That's fine for all the images or fonts which are encoded into the CSS as data URIs (i.e. the content of the file is embedded in the CSS), but for assets referenced by URL, the browser has to find and fetch the file.
Now by default the file-loader (which url-loader delegates to for large files) will use relative URLs to reference assets - and that's the problem!
These are the URLs generated by file-loader by default - relative URLs
When you use relative URLs, Chrome will resolve them relative to the containing CSS file. Ordinarily that's fine, but in this case the containing file is at blob://... and any relative URLs are referenced the same way. The end result is that Chrome attempts to load them from the parent HTML file, and ends up trying to parse the HTML file as the content of the font, which obviously won't work.
The Solution
Force the file-loader to use absolute paths including the protocol ("http" or "https").
Change your webpack config to include something equivalent to:
{
output: {
publicPath: "http://localhost:8080/", // Development Server
// publicPath: "http://example.com/", // Production Server
}
}
Now the URLs that it generates will look like this:
Absolute URLs!
These URLs will be correctly parsed by Chrome and every other browser.
Using extract-text-webpack-plugin
It's worth noting that if you're extracting your CSS to a separate file, you won't have this problem because your CSS will be in a proper file and URLs will be correctly resolved.
For me the problem was my regex expression. The below did the trick to get bootstrap working:
{
test: /\.(woff|ttf|eot|svg)(\?v=[a-z0-9]\.[a-z0-9]\.[a-z0-9])?$/,
loader: 'url-loader?limit=100000'
},
As asnwered here by #mcortesi if you remove the sourceMaps from the css loader query the css will be built without use of blob and the data urls will be parsed fine
As with #user3006381 above, my issue was not just relative URLs but that webpack was placing the files as if they were javascript files. Their contents were all basically:
module.exports = __webpack_public_path__ + "7410dd7fd1616d9a61625679285ff5d4.eot";
in the fonts directory instead of the real fonts and the font files were in the output folder under hash codes. To fix this, I had to change the test on my url-loader (in my case my image processor) to not load the fonts folder. I still had to set output.publicPath in webpack.config.js as #will-madden notes in his excellent answer.
I experienced the same problem, but for different reasons.
After Will Madden's solution didn't help, I tried every alternative fix I could find via the Intertubes - also to no avail. Exploring further, I just happened to open up one of the font files at issue. The original content of the file had somehow been overwritten by Webpack to include some kind of configuration info, likely from previous tinkering with the file-loader. I replaced the corrupted files with the originals, and voilà, the errors disappeared (for both Chrome and Firefox).
I know this doesn't answer OPs exact question but I came here with the same symptom but a different cause:
I had the .scss files of Slick Slider included like this:
#import "../../../node_modules/slick-carousel/slick/slick.scss";
On closer inspection it turned out that the it was trying to load the font from an invalid location (<host>/assets/css/fonts/slick.woff), the way it was referenced from the stylesheet.
I ended up simply copying the /font/ to my assets/css/ and the issue was resolved for me.
Since you use url-loader:
The url-loader works like the file-loader, but can return a DataURL if the file is smaller than a byte limit.
So another solution to this problem would be making the limit higher enough that the font files are included as DataURL, for example to 100000 which are more or less 100Kb:
{
module: {
loaders: [
// ...
{
test: /\.scss$/,
loaders: ['style', 'css?sourceMap', 'autoprefixer', 'sass?sourceMap'],
},
{
test: /images\/.*\.(png|jpg|svg|gif)$/,
loader: 'url-loader?limit=10000&name="[name]-[hash].[ext]"',
},
{
test: /\.woff(\?v=\d+\.\d+\.\d+)?$/,
use: 'url-loader?limit=100000&mimetype=application/font-woff',
},
{
test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/,
use: 'url-loader?limit=100000&mimetype=application/font-woff',
},
{
test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
use: 'url-loader?limit=100000&mimetype=application/octet-stream',
},
{
test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
use: 'file-loader',
},
{
test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
use: 'url-loader?limit=100000&mimetype=image/svg+xml',
},
],
},
}
Allways taking into account on what the limit number represents:
Byte limit to inline files as Data URL
This way you don't need to specify the whole URL of the assets. Which can be difficult when you want Webpack to not only respond from localhost.
Just one last consideration, this configuration is NOT RECOMMENDED for production. This is just for development easiness.
The best and easiest method is to base64 encode the font file. And use it in font-face.
For encoding, go to the folder having the font-file and use the command in terminal:
base64 Roboto.ttf > basecodedtext.txt
You will get an output file named basecodedtext.txt. Open that file. Remove any white spaces in that.
Copy that code and add the following line to the CSS file:
#font-face {
font-family: "font-name";
src: url(data:application/x-font-woff;charset=utf-8;base64,<<paste your code here>>) format('woff');
}
Then you can use the font-family: "font-name" in your CSS.
I just had the same issue with Font Awesome. Turned out this was
caused by a problem with FTP. The file was uploaded as text (ASCII)
instead of binary, which corrupted the file. I simply changed my FTP
software to binary, re-uploaded the font files, and then it all
worked.
https://css-tricks.com/forums/topic/custom-fonts-returns-failed-to-decode-downloaded-font/
this helped me in the end
I had the same issue with FTP transferring files as text
If you're using Angular you need to check to make sure your
<base href="/">
tag comes before your style sheet bundle. I switched my code from this:
<script src="~/bundles/style.bundle.js"></script>
<base href="~/" />
to this:
<base href="~/" />
<script src="~/bundles/style.bundle.js"></script>
and the problem was fixed.
Thanks to this post for opening my eyes.
As of 2018,
use MiniCssExtractPlugin
for Webpack(> 4.0) will solve this problem.
https://github.com/webpack-contrib/mini-css-extract-plugin
Using extract-text-webpack-plugin in the accepted answer is NOT recommended for Webpack 4.0+.
The limit was the clue for my code, but I had to specify it like this:
use: [
{
loader: 'url-loader',
options: {
limit: 8192,
},
},
],
In my case adding following lines to lambda.js {my deployed is on AWS Lambda} fixed the issue.
'font/opentype',
'font/sfnt',
'font/ttf',
'font/woff',
'font/woff2'
Had same problem like #adam-mccormick and user3006381. I am using webpack5 and hot module.
My .eot or .woff files contained:
export default __webpack_public_path__ + "./fonts/montserrat-v24-latin-ext-regular.woff2";
and my webpack.config.js looked like:
modules.exports = {
//...
module: {
rules: [
//...
{
test: /\.(woff|woff2|eot|ttf|otf)$/i,
use: [{
loader: "file-loader",
options: {
name: './fonts/[name].[ext]',
}
}]
}
]
}
}
and this was my problem solution:
modules.exports = {
//...
module: {
rules: [
//...
{
test: /\.(woff|woff2|eot|ttf|otf)$/i,
type: 'asset/resource',
generator: {
filename: './fonts/[name].[ext]',
}
}
]
}
}

Resources