Unable to inline fonts from npm modules - html

I am running Angular 8 with the Custom Webpack builder.
"builder": "#angular-builders/custom-webpack:browser",
I have a reference to the ngx-datatable, and I reference the css as follows:
#import '~#swimlane/ngx-datatable/release/assets/icons.css';
That referenced css file has a font-face like so:
#font-face {
font-family: "data-table";
src:url("fonts/data-table.eot");
src:url("fonts/data-table.eot?#iefix") format("embedded-opentype"),
url("fonts/data-table.woff") format("woff"),
url("fonts/data-table.ttf") format("truetype"),
url("fonts/data-table.svg#data-table") format("svg");
font-weight: normal;
font-style: normal;
What I want to do is inline the data-table font file into my webpack'd build. My understanding is that, after installing the base64-inline-loader, I should be able to have a custom webpack config that looks like this:
module.exports = {
module: {
rules: [
{
test: /\.(jpe?g|png|ttf|eot|svg|woff(2)?)(\?[a-z0-9=&.]+)?$/,
use: 'base64-inline-loader'
}
]
}
};
However, after running the build, nothing gets inlined, and I can see the browser is making a request to
http://localhost:4200/data-table.woff
It's not clear to me how to fix this. My understanding is that for files like .png, .woff, .eot, etc, the default Angular webpack configuration will use the file-loader, which will spit out a hashed version of the file in the dist directory. However even after adding the base64-inline-loader, I am still seeing the files get copied and hashed, instead of inlined.
Edit
I believe my problem is related to Angular 7, svg and sass how to set relative path, but I'm still not sure how to fix it.

Could it be that your Webpack.config.js might need some tweaking?
I prefer to keep the command line clean (here: webpack --config Webpack.config.js) and put everything into the configuration file. Assuming that you are using a newer version of Webpack, I suggest a configuration file similar to this this
var path = require('path'); // this is essential for path.resolve()
module.exports = {
mode: 'development',
entry: './yourEntryPage.js',
output: {
path: path.resolve(__dirname, 'dist'), // specifies the output
filename: 'bundle.js'
},
devtool: "source-map", // for debugging webpack's output.
module: {
rules: [
{ test: /\.jsx$|\.es6$|\.js$/,
use: {
loader: 'babel-loader',
options: {
presets: ['react'],
}
},
exclude: /node_modules/
},
{ test: /\.(png|jpg|gif)$/,
use: {
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'images/'
}
}
},
{ test: /\.(ttf|eot|woff(2)?)$/, // modified regex matching files with font extension
use: 'base64-inline-loader'
}
]
}
};
You cannot directly use this configuration file, but I hope my suggestion gives you an idea on what a not-so-minimal configuration for Webpack could look like. The Webpack.config.js you suggested might not only have a path problem, but might also miss to specify the hierarchy of the different loaders. It could well be that your inline-loader case-statement is never reached.
Note: I do not know #angular-builders/custom-webpack:browser, but I hope it helps anyhow if that package does not interfere too much with Webpack.config.js. My experience tells me that in 95% of the cases the cuplrit is a webpack configuration issue. A --verbose, --progress or -d might become handy, see Webpack's CLI documentation.

The webpack will inline the font into your output .js file (or .woff file) but will not serve it. This means that you have to manually add this font in your static assets in angular.json:
"assets": [
"src/assets",
{
"glob": "**/*",
"input": "node_modules/swimlane_or_whatever/assets/",
"output": "my-assets"
},
The code above means that after you run the development server, the resource /my-assets/fonts.woff will be resolved and passed to the client.

Related

Have problem with importing image in react

Hello everyone I have some problems with importing images to my project. I tried before to import image on my old project the way that i did was working but not for that time. I imported image like:
import Fav from '../img/fav.png'
My file path is in src/img/fav.png and I'm trying to import from src/components/App.jsx
So the error I have is :
ERROR in ./img/fav.png 1:0
Module parse failed: Unexpected character '�' (1:0)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
(Source code omitted for this binary file)
# ./components/App.jsx 3:0-33
# ./entry.jsx
# multi ./entry.jsx
I tried to find some solutinons in the web bu i couldn't find.
Thanks for help
You need a webpack loader to load the image, e.g. file-loader:
{
test: /\.(png|jpg|gif|svg)$/,
use: [
{
loader: 'file-loader',
options: {
outputPath: 'images',
},
},
],
},
The solution was here:
{
test: /\.(png|svg|jpg|gif)$/,
include: path.resolve(__dirname, 'src/assets'),
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]'
}
}
]
}
The path is included by default.

Webpack - Yaml -> JSON -> Extract file

I have a YAML file with a few translations. I need to transform these files into a JSON file. I've tried using yaml-import-loader and json-loader but I get an error.
Here's my setup:
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const extractEnglish = new ExtractTextPlugin('lang/en.js');
module.exports = {
entry: [
'./src/locales/application.en.yml',
],
output: {
filename: 'english.js',
},
module: {
strictExportPresence: true,
rules: [
{
test: /\.en\.yml$/,
use: extractEnglish.extract({
use: [
// { loader: 'json-loader' },
{
loader: 'yaml-import-loader',
options: {
output: 'json',
},
}],
}),
},
],
},
plugins: [
extractEnglish,
],
};
And the error I get:
Users/xxx/Documents/Project/node_modules/extract-text-webpack-plugin/dist/index.js:188
chunk.sortModules();
^
TypeError: chunk.sortModules is not a function
at /Users/xxx/Documents/Project/node_modules/extract-text-webpack-plugin/dist/index.js:188:19
Same error whether or not the json-loader is commented or not.
I really don't understand what is going wrong.
Versions:
"webpack": "2.6.1",
"extract-text-webpack-plugin": "^3.0.0",
"json-loader": "^0.5.7",
Not sure if this will help your situation but I recently found a solution to my i18n loading problem. I do this to extract YAML into JSON files upfront as I use angular-translate and needed to load files dynamically and on-demand. I avoid extract-text-webpack-plugin and use only loaders: file-loader and yaml-loader.
First I setup the import of my .yaml files near the beginning of source (in my case a specific chain of import files for webpack to process)
import "./i18n/en.user.yaml";
I updated webpack config to translate YAML to JSON and have it available to load dynamically (everything originates from my 'src' directory, hence the context):
rules: [{
test: /.\.yaml$/,
use: [{
loader: 'file-loader',
options: {
name: '[path][name].json',
context: 'src'
}
},{
loader: 'yaml-loader'
}]
}]
This will translate my yaml file(s) and export them to my public directory, in this case at '/i18n/en.user.json'.
Now when angular-translate uploads my configured i18n settings via $http on-demand, it already has the parsed YAML and avoids having to parse it with js-yaml (or similar) on the front end.
A relatively old question, but I found it while searching for a solution to the same problem, so I thought it worth to chip in.
If you're not really using translation files in your code (i.e. you never import and use them directly) then using a Webpack loader is not the most elegant solution (you'd be forced to import them just so that the loader could be triggered and perform the conversion).
An alternative would be to use the CopyWebpackPlugin instead: it supports a transform option, which takes a function receiving the content of the file as a Buffer.
With a YAML parser (like js-yaml) as an additional dependency, adding this to your Webpack configuration would work:
const yaml = require('js-yaml');
const CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = {
// OTHER WEBPACK CONFIG HERE
plugins: [
new CopyWebpackPlugin({
patterns: [
{
from: 'i18n/**/*',
to: 'i18n/[name].json',
transform(content) {
return Buffer.from(
JSON.stringify(
yaml.load(content.toString('utf8'), {
schema: yaml.JSON_SCHEMA
})
),
'utf8'
)
}
}
]
})
]
}
The i18n folder in the above example would contain your .yml translations.
The Copy plugin would load them, convert them to JSON, and save them in the output folder under i18n/ (as specified by the to option).

Copy multiple html files with webpack2 (from src to dist folder)

Which loader/plugin should I use to move multiple html files from one folder (src) to another (dist) which only imports files that obey certain rules in this example I need to import multiple html files, so the regex would be:
/.html$/
I know that I can move html using html-webpack-plugin but I don't want to create object instance for every page I want to move. I also don't want to make multiple imports in my app.js (entry point for webpack).
So i tried with copy-webpack-plugin but this one moves everything from src to dist. Is it possible to filter with my regex pattern or do you know other way that works to do this?
new CopyWebpackPlugin([{
from: './src',
to: path.resolve(__dirname, "dist")
}],
I gues that I could use system
mkdir dist && cp ./src/*.html ./dist
And simply run this in my package.json in the script before running webpack -d
but this is not the "polite" way of doing this. I'm sure that webpack can do that easily..
Ps. Also, it would be nice to minimize those files, if possible.
Moving all files in batch
So for now it works like this. To not have to include every single file from the src folder in to my app.js (which is my entry point for webpack) I required all files using require.context()
Because my app.js is also in my src folder I use relative path to require all other file:
// requires all files in current directory and sub directories
require.context("./", true, /^\.\/.*\..*/);
Or if you want to import files with certain extension sue this instead:
// requires all html files in current directory and sub directories
require.context("./", true, /^\.\/.*\.html/);
So now everything is imported and I don't have to require files manually. The only thing I have to do is set entry to app.js using path.resolve.
I now can use test property to get what I want from within in webpack.config.js module rules.
...
module: {
rules: [
{
test: /\.(html)$/,
use:
[
{
loader: 'file-loader',
options: {
name: '[path][name].[ext]',
context: './src',
outputPath: '/',
publicPath: '/'
}
},
...
This works fine my files are moved (but not minified). Perhaps someone can take this a little bit further and the answer will be completed.
Below i place full file for reference only
webpack.config.js
// imports node plugin which allows us to save data to a file for example css external files
var ExtractTextPlugin = require("extract-text-webpack-plugin");
// cleans defined folders before webpack will build new files now we can remove package.json commands "rm -rf ./dist && ..."
var CleanWebpackPlugin = require("clean-webpack-plugin");
// copies to memory html from template file and injects css and javascript as well as img src to newly generated html file.
var HtmlWebpackPlugin = require("html-webpack-plugin");
// to include jquery we need to import 'jquery' in app.js but also we need to make connection between bundle.js jquery script
var Webpack = require('webpack');
// includes node path resover that is need for webpack-dev-server to run properly
var path = require('path');
// webpack configuration
module.exports = {
entry: [
path.resolve(__dirname, "src/app.js"),
],
output: {
path: path.resolve(__dirname, 'dist'), // defins the main utput directory
filename: 'js/bundle.js',
},
devServer: {
contentBase: path.join(__dirname, "dist"),
compress: true,
port: 8080,
},
module: {
rules: [
{
test: /\.(html)$/,
use:
[
{
loader: 'file-loader',
options: {
name: '[path][name].[ext]',
context: './src',
outputPath: '/',
publicPath: '/'
}
},
]
},
{
test: /\.(jpg|png|gif)$/,
use: {
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'img/',
publicPath: '/' // this path relates to reference path from the index.html file that imports out bundle.js file
}
}
},
{
test: /\.js$/,
use: [
{
loader: 'babel-loader',
options: {
presets: ['es2015']
}
}
]
},
{
test: /\.sass$/,
include: [
path.resolve(__dirname, "src/sass")
],
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
//resolve-url-loader may be chained before sass-loader if necessary
use: [
{
loader: 'css-loader',
options: {
minimize: false,
sourceMap: true,
}
},
'sass-loader'
]
})
},
]
},
plugins: [
// mapping jQuery variable to our node module dependency (remember to import 'jquery' in app.js)
// below we make jquery available as both the $ and jQuery variable
new Webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery'
}),
// use extract plugin to build an external file loded by sass-loader > complied to css > movig to bundle.css
new ExtractTextPlugin({
filename: 'css/bundle.css'
}),
// remove all files from this folder before generating new files
// new CleanWebpackPlugin(['dist']),
],
}
You should be able to use copy-webpack-plugin's support for globs to achieve what you want.
new CopyWebpackPlugin([
{
from: './src/*.html',
to: path.resolve(__dirname, 'dist')
}
])
The globs accept minimatch options too.
EDIT:
In addition, if you're copying just HTML (and want to minify them), you might want to take a look at html-webpack-plugin. The minify option allows you to minify those HTML files.

Concat and minify CSS files with Webpack without require them

I've got and old part of an application that contains some CSS files that are concatenated and minified with gulp script.
And I've got a new application that bundled with Webpack.
Is it possible to assemble the old CSS with Webpack without any additional require calls? Just get all CSS from old_css/**/*.css, concat, minify and write to assets/old.css?
You can achieve this by "requiring" the CSS files through a separate entry. You'll end up with something like this:
{
entry: {
styles: glob('old_css/**/*.css'), // array of css files
...
},
output: {
filename: '[name].[chunkhash].js',
...
},
module: {
loaders: [
{
test: /\.css$/,
loader: ExtractTextPlugin.extract("style-loader", "css-loader")
},
...
]
},
plugins: [
new ExtractTextPlugin('[name].[chunkhash].css'),
...
],
...
}
You'll end up with a JavaScript file named after your style entry in addition to the CSS file. You can ignore that, though.

How to inject bower dependencies in karma.conf.js file with gulp?

How to inject bower dependencies in karma.conf.js file with gulp?
I tried wiredep task - but it doesn't work with .js files and it inserts tag with path to dependency, but I need just path in quotes.
In case the version of wiredep you're making use of doesn't support .js files, you can include the fileTypes node in your wiredep configuration file. This is what I have in my project:
wiredep Configuration:
...,
src:
[
'<%= myApp.webRoot %>/index.html',
'./karma.conf.js'
],
...,
fileTypes: {
js: {
block: /(([ \t]*)\/\/\s*bower:*(\S*))(\n|\r|.)*?(\/\/\s*endbower)/gi,
detect: {
js: /['\']([^'\']+\.js)['\'],?/gi,
css: /['\']([^'\']+\.js)['\'],?/gi
},
replace: {
js: '"{{filePath}}",',
css: '"{{filePath}}",'
}
}
},
...
kamra.conf.js
...,
files:
[
// bower:js
// endbower
'your/other/**/dependencies/*.here.js'
],
...
Also, make sure that the path to your karma.conf.js is correct as even if the file is not found you won't get any warnings or errors.