I'm trying to include an image in my twig template just like simple tag, but it doesn't want to include. For build, I use HtmlWebpackPlugin and twig-loader;
But if I do the same with html-loader and html template - it works fine.
How to do it right with twig-loader?
my webpack-config:
const path = require( 'path' );
const HtmlWebpackPlugin = require( 'html-webpack-plugin' );
const PATHS = {
source: path.join( __dirname, './source' ),
build: path.join( __dirname, './build' )
};
module.exports = {
entry: `${ PATHS.source }/index.js`,
output: {
path: PATHS.build,
filename: 'webpack.bundle.js'
},
module: {
rules: [
{
test: /\.twig/,
loader: 'twig-loader'
},
{
test: /.*\.(gif|png|jpe?g)$/i,
use: [
{
loader: 'file-loader?name=[name].[ext]'
}
]
}
]
},
plugins: [
new HtmlWebpackPlugin( {
filename: 'index.html',
template: `${PATHS.source}/index.twig`,
} )
],
};
my twig template:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<img src="./chuck-norris.jpg" alt="">
</body>
</html>
my package.json:
{
"name": "htmlWebpackPlugin-twigLoader",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "webpack"
},
"author": "evisotskiy",
"license": "ISC",
"devDependencies": {
"file-loader": "^0.11.2",
"html-loader": "^0.5.1",
"html-webpack-plugin": "^2.30.1",
"twig-loader": "^0.3.1",
"webpack": "^3.6.0"
}
}
my project's structure:
.
├── webpack.config.js
├── package.json
├── source
| ├──index.twig
| ├──index.js (empty)
| ├──chuck-norris.jpg
and when I execute npm run build I get dir:
├── build
| ├──index.html
| ├──webpack.bundle.js
without chuck-norris.jpg
And when I use html-loader instead twig-loader and html-template instead twig-template - image builds fine. But for my project, I need to use twig templates.
How to do it right with twig-loader?
I have found a solution. Instead of passing to HtmlWebpackPlugin as template the .twig-file directly, I passed as template a .js-file, inside of which I included a .twig file and image, and passed the image to the twig-template as a variable. Now the project looks like this:
my webpack-config:
const path = require( 'path' );
const HtmlWebpackPlugin = require( 'html-webpack-plugin' );
const PATHS = {
source: path.join( __dirname, './source' ),
build: path.join( __dirname, './build' )
};
module.exports = {
entry: `${ PATHS.source }/index.js`,
output: {
path: PATHS.build,
filename: 'webpack.bundle.js'
},
module: {
rules: [
{
test: /\.twig$/,
loader: 'twig-loader'
},
{
test: /.*\.(gif|png|jpe?g)$/i,
use: [
{
loader: 'file-loader?name=[name].[ext]'
}
]
}
]
},
plugins: [
new HtmlWebpackPlugin( {
filename: 'index.html',
template: `${PATHS.source}/index.twig.js`,
} )
],
};
my twig template:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<img src="{{ image.src }}" alt="{{ image.alt }}">
</body>
</html>
my index.twig.js:
const template = require( './index.twig' );
const image = {
src: require( './chuck-norris.jpg' ),
alt: "Chuck Norris"
};
module.exports = template( { image } );
my package.json:
{
"name": "htmlWebpackPlugin-twigLoader",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "webpack"
},
"author": "evisotskiy",
"license": "ISC",
"devDependencies": {
"file-loader": "^0.11.2",
"html-webpack-plugin": "^2.30.1",
"twig-loader": "^0.3.1",
"webpack": "^3.6.0"
}
}
my project's structure:
.
├── webpack.config.js
├── package.json
├── source
| ├──index.twig
| ├──index.twig.js
| ├──index.js (empty)
| ├──chuck-norris.jpg
and when I execute npm run build I get builded project I expected:
├── build
| ├──index.html
| ├──chuck-norris.jpg
| ├──webpack.bundle.js
I faced the same problem recently. But I could not use a solution with handling URLs as parameters.
I've fixed it with extract-loader and html-loader.
Honestly, I don't know how it works, but it works.
This is a task for gulp.
See rules with test: /\.(jpeg|png|svg|jpg|gif)$/i, and test: /\.twig$/,
//region js
task('app:compile', function(){
return src(path.js.src)
.pipe(named())
.pipe(webpack({
mode: 'development',
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env'],
plugins: ['#babel/plugin-proposal-object-rest-spread']
}
}
},
{
test: /\.(scss|css)$/,
exclude: /(node_modules|bower_components)/,
use: [
{loader: "style-loader"},
{loader: "css-loader"},
{loader: "sass-loader"},
],
},
{
test: /\.(jpeg|png|svg|jpg|gif)$/i,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: '../images',
publicPath: 'images',
}
},
],
},
{
test: /\.twig$/,
use: [
'twig-loader',
'extract-loader',
{
loader:'html-loader',
},
],
},
{
test:/\.(woff|woff2|eot|ttf|otf)$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: '../fonts',
publicPath: 'fonts',
}
},
],
},
],
},
devtool: 'source-map',
}))
.pipe(dest(path.js.dest));
});
//endregion
You can see the full version of gulpfile.js at the link
landing_scratch gulpfile.js
Hope it helps somebody who is googling the same questions.
If it's any help, I fixed this very same problem by simply changing the loader that processes the twig template files and adding "html-loader".
This would be the change:
{
test: /\.twig$/,
loader: 'twig-loader'
}
to
{
test: /\.twig$/,
exclude: /node_modules/,
use: [
'html-loader',
'twig-html-loader'
]
}
Of course, you must install those loaders previously if you didn't do it yet.
npm install twig-html-loader html-loader --save-dev
Henceforth, the images will be processed ;)
I incorporated Twig templates in my advanced SPA build with Vue CLI. The issue I faced was the same as the topic starter.
My Twig templates were compiled fine. But the images in the templates were not copied to build folder. And the paths in resulting output HTML files were not transformed into their Webpack-built-and-hashed paths.
At the same time the images in .vue files were copied and the images paths were updated.
To solve this I applied the core of the solution from #s.smsmsm above to my context. Thanks mate.
Briefly: you have to make Webpack to use 3 loaders to process your Twig templates. These are twig-loader, extract-loader and html-loader.
For this I made the specifig vue.config.js.
See it here with more explanations. The short version follows.
// vue.config.js
module.exports = {
runtimeCompiler: true,
outputDir: '.dist',
pages: {
main: {
entry: 'src/js/main.js',
template: 'src/views/pages/index.twig',
filename: 'index.html'
}
},
// Here is where the fix actually is made.
chainWebpack: config => {
config.module
.rule('twig')
.test(/\.twig$/)
.use('twig-loader')
.loader('twig-loader')
.end()
.use('extract-loader')
.loader('extract-loader')
.end()
.use('html-loader')
.loader('html-loader')
.end();
}
};
The Vue CLI config reference is here. Its chainWebpack option was used to modify the respective Webpack config part via vue.config.js. How to add a new loader doc is here.
Related
I'm trying to call a background URL in an scss file but webapack give me an error of compilation.
My project structur is :
dist
bundle.js
main.css
src
public
assets
css
scss
components
myfile.scss (insid components)
main.scss
img
js
index.html
app.js
webpack.config.js
This is the code which contains the error:
&:after{
content:"";
background: url('./../../../img/curve3.png') 100%;
position: absolute;
bottom:0;
left: 0;
right: 0;
height: 170px;
}
This is what I got from the webpack console:
ERROR in ./src/public/assets/css/scss/main.scss (./node_modules/css->loader/dist/cjs.js??ref--5-2!./node_modules/resolve-url->loader!./node_modules/postcss-loader/src??postcss!./node_modules/sass->loader/lib/loader.js!./src/public/assets/css/scss/main.scss)
Module not found: Error: Can't resolve './../../../img/curve3.png' >in >'/Users/retinas/Documents/Devloppement/static/um6/src/public/assets/css>/scss'
# ./src/public/assets/css/scss/main.scss (./node_modules/css->loader/dist/cjs.js??ref--5-2!./node_modules/resolve-url->loader!./node_modules/postcss-loader/src??postcss!./node_modules/sass->loader/lib/loader.js!./src/public/assets/css/scss/main.scss) 23:42-78
My webpack config :
const path = require('path');
const dev = process.env.NODE_ENV === 'dev';
const ExtractTextPlugin = require("extract-text-webpack-plugin");
module.exports = {
mode: "development",
entry: "./src/app.js",
watch: dev,
devServer: {
contentBase: path.resolve('./'),
publicPath: '/assets/',
port: 3000
},
output: {
path: path.resolve(__dirname, "./dist"),
filename: "bundle.js"
},
module : {
rules : [
{
enforce: 'pre',
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'eslint-loader',
}
},
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
}
},
{
test: /\.scss$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: [
{ loader: 'css-loader?url=false', options: { importLoaders: 1 } },
{ loader: 'resolve-url-loader' },
{
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: () => [
require('autoprefixer')({
browsers : ['last 2 versions', 'ie > 8']
}),
]
}
},
'sass-loader'
]
})
},
{
test: /\.(png|jpg|woff|woff2|eot|ttf|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
loader: 'url-loader?limit=100000'
}
]
},
plugins: [
new ExtractTextPlugin({
filename : '[name].css',
disable : dev
}),
]
}
Thanks for your help
Finally, I found the solution of the problem, it was in the URL path it should be like this:
background: url('./../../img/curve3.png') 100%;
not this :
background: url('./../../../img/curve3.png') 100%;
I should began from the main.scss not from myfile.scss
Thanks.
I have my scss file which imports a scss file which further imports bourbon and bourbon-neat. I even searched various issues on the forum but did not find the issue where in the scsss to css conversion, the case is to include bourbon.
webpack 4.28.1
mini-css-extract-plugin 0.5.0
I am seeing the following error:
Child mini-css-extract-plugin node_modules/css-loader/dist/cjs.js!node_modules/sass-loader/lib/loader.js??ref--5-2!src/component/styles/main.scss:enter code here
Entrypoint mini-css-extract-plugin = *
[./node_modules/css-loader/dist/cjs.js!./node_modules/sass-loader/lib/loader.js?!./src/component/styles/main.scss] ./node_modules/css-loader/dist/cjs.js!./node_modules/sass-loader/lib/loader.js??ref--5-2!./src/component/styles/main.scss 373 bytes {mini-css-extract-plugin} [built] [failed] [1 error]
ERROR in ./src/component/styles/main.scss (./node_modules/css-loader/dist/cjs.js!./node_modules/sass-loader/lib/loader.js??ref--5-2!./src/component/styles/main.scss)
Module build failed (from ./node_modules/sass-loader/lib/loader.js):
var path = require('path');
^
Invalid CSS after "v": expected 1 selector or at-rule, was "var path = require("
in /Users/../node_modules/bourbon/index.js (line 1, column 1)
My webpack.config.js file is here
const path = require('path');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
module.exports = {
entry: {
"app": ['whatwg-fetch',"./src/component/index.ts", "./src/component/styles/main.scss"],
"app-helper": "./src/component/helpers.ts"
},
output: {
path: path.resolve(__dirname, './src/component/dist'),
filename: "[name].bundle.js"
},
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/
},
test: /\.(sa|sc|c)ss$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
{
loader: "sass-loader",// compiles Sass to CSS
options: {
includePaths: [
'node_modules/bourbon/app/assets/stylesheets',
'node_modules/bourbon-neat/app/assets/stylesheets'
]
}
}
],
]
},
plugins: [
new MiniCssExtractPlugin({
filename: './src/component/dist/output-style.css',
})
],
optimization: {
minimizer:[
new UglifyJSPlugin({
cache: true,
parallel: true,
sourceMap: true // set to true if you want JS source maps
}),
new OptimizeCSSAssetsPlugin({})
]
}
}
Please provide your valuable suggestions.
This turns out to be an issue with sass-loader version 7.x . I changed sass-loader dependency back to 6.0.7 and it started working like charm. Here is the stackoverflow thread which helped
Angular 2 Node Bourbon Error
The problem
Im using webpack 4 to compile scss to css and MiniCssExtractPlugin to save the css into a different file. The problem is, that i dont manage to load images and fonts, that are included via url() inside of the scss files. It also makes no difference between running development or production.
Scss is compiled perfectly and without any problems. Also the scss-loader has no problems loading .scss-files from node_modules.
Why does this error occur and how can i fix it?
error-message when running npm
ERROR in ./ui/index.scss (./node_modules/css-loader!./node_modules/sass-loader/lib/loader.js!./ui/index.scss)
Module not found: Error: Can't resolve '../webfonts/fa-solid-900.woff' in '/home/asdff45/Schreibtisch/Programme/GO/src/factorio-server-manager/manager/ui'
# ./ui/index.scss (./node_modules/css-loader!./node_modules/sass-loader/lib/loader.js!./ui/index.scss) 7:336881-336921
ERROR in ./ui/index.scss (./node_modules/css-loader!./node_modules/sass-loader/lib/loader.js!./ui/index.scss)
Module not found: Error: Can't resolve '../webfonts/fa-solid-900.woff2' in '/home/asdff45/Schreibtisch/Programme/GO/src/factorio-server-manager/manager/ui'
# ./ui/index.scss (./node_modules/css-loader!./node_modules/sass-loader/lib/loader.js!./ui/index.scss) 7:336799-336840
And multiple more, but all have the same error, just the filename changes.
webpack-Config
const path = require('path');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
entry: {
// js: './ui/index.js',
sass: './ui/index.scss'
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'app')
},
resolve: {
alias: {
Utilities: path.resolve(__dirname, 'ui/js/')
},
extensions: ['.js', '.json', '.jsx']
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader'
}
},
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader",
"sass-loader"
]
},
{
test: /(\.(png|jpe?g|gif)$|^((?!font).)*\.svg$)/,
loaders: [
{
loader: "file-loader",
options: {
name: loader_path => {
if(!/node_modules/.test(loader_path)) {
return "app/images/[name].[ext]?[hash]";
}
return (
"app/images/vendor/" +
loader_path.replace(/\\/g, "/")
.replace(/((.*(node_modules))|images|image|img|assets)\//g, '') +
'?[hash]'
);
},
}
}
]
},
{
test: /(\.(woff2?|ttf|eot|otf)$|font.*\.svg$)/,
loaders: [
{
loader: "file-loader",
options: {
name: loader_path => {
if (!/node_modules/.test(loader_path)) {
return 'app/fonts/[name].[ext]?[hash]';
}
return (
'app/fonts/vendor/' +
loader_path
.replace(/\\/g, '/')
.replace(/((.*(node_modules))|fonts|font|assets)\//g, '') +
'?[hash]'
);
},
}
}
]
}
]
},
performance: {
hints: false
},
plugins: [
new MiniCssExtractPlugin({
filename: "bundle.css"
})
]
}
Project Repo/Branch
You need to add resolve-url-loader to your build, like this:
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader",
"resolve-url-loader",
"sass-loader?sourceMap"
]
}
resolve-url-loader is resolving paths to assets based on the original file that is importing the asset.
I tried it locally and the build is now passing :) Cheers!
Given a Laravel 5.5 project, I want to use the "single file component" of the vue-i18n plugin. Documentation. It seems simple, but I can't get it to work.
app.js
import VueI18n from 'vue-i18n'
Vue.use(VueI18n)
const i18n = new VueI18n({
locale: 'en',
messages: {
"en": {
"word1": "hello world!"
}
}
})
Vue.component('test', require('./components/test.vue'));
const app = new Vue({ i18n, el: '#apps'});
components/test.vue
<template>
{{ $t('word1') }}
{{ $t('word2') }}
</template>
<i18n>
{
"en": {
"word2": "does this work?"
}
}
</i18n>
<script>
export default {
name: "test"
data() {
return {
locale: 'en'
}
},
mounted() {},
watch: {
locale (val) {
this.$i18n.locale = val
}
}
}
</script>
word1 is being replaced, however word2 is not. Placing bad syntax between the i18n-tags in the vue file, does NOT result in an error while compiling the files (npm run dev). This makes sense, because I'm missing the:
Taken from the documentation
module.exports = {
// ...
module: {
rules: [
...
This is supposed to go in the Webpack configuration. But, where is this file in laravel? All I can find is the webpack.mix.js, but placing this code in there, does not do much... Also making it mix.module.exports does not do the trick. Searching led me to this topic, but i'm not sure if he's asking the same as I am.
The problem: the i18n-tags aren't loaded. The solution is to add the code from the documentation.
My question: Where do I add this code?
To anyone stumbling upon the same problem, I proposed a change in the documentation:
https://github.com/kazupon/vue-i18n/pull/237
Laravel mix has its own rules for .vue files. To add the vue-i18n-loader, add the following to webpack.mix.js
mix.webpackConfig({
// ...
module: {
rules: [
{
// Rules are copied from laravel-mix#1.5.1 /src/builder/webpack-rules.js and manually merged with the ia8n-loader. Make sure to update the rules to the latest found in webpack-rules.js
test: /\.vue$/,
loader: 'vue-loader',
exclude: /bower_components/,
options: {
// extractCSS: Config.extractVueStyles,
loaders: Config.extractVueStyles ? {
js: {
loader: 'babel-loader',
options: Config.babel()
},
scss: vueExtractPlugin.extract({
use: 'css-loader!sass-loader',
fallback: 'vue-style-loader'
}),
sass: vueExtractPlugin.extract({
use: 'css-loader!sass-loader?indentedSyntax',
fallback: 'vue-style-loader'
}),
css: vueExtractPlugin.extract({
use: 'css-loader',
fallback: 'vue-style-loader'
}),
stylus: vueExtractPlugin.extract({
use: 'css-loader!stylus-loader?paths[]=node_modules',
fallback: 'vue-style-loader'
}),
less: vueExtractPlugin.extract({
use: 'css-loader!less-loader',
fallback: 'vue-style-loader'
}),
i18n: '#kazupon/vue-i18n-loader',
} : {
js: {
loader: 'babel-loader',
options: Config.babel()
},
i18n: '#kazupon/vue-i18n-loader',
},
postcss: Config.postCss,
preLoaders: Config.vue.preLoaders,
postLoaders: Config.vue.postLoaders,
esModule: Config.vue.esModule
}
},
// ...
]
},
// ...
});
preface
I am currently switching our build process over from Browserify to Webpack. As the project uses a great deal of coffee-script, I have many import statements such as:
require('./coffee-file-without-extension') # note the lack of .coffee
require('./legacy-js-file-without-extension') # note the lack of .js
problem
Browserify handles the absence of the file extension just fine. Webpack seems to have issue per this error:
Module not found: Error: Can't resolve './wptest-req' in '/Users/jusopi/Dev/Workspaces/nx/nx-ui/src'
I setup a super simple test project for this where I have the following files:
wptest.coffee
require('./wptest-req')
wptest-req.coffee
module.exports = {}
webpack.config.js
const path = require('path');
const webpack = require('webpack')
module.exports = {
entry: {
main: './src/wptest.coffee'
},
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'dist')
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: 'common' // Specify the common bundle's name.
})
],
module: {
rules: [
{
test: /\.coffee$/,
use: [
{
loader: 'coffee-loader',
options: { sourceMap: true }
}
]
}
]
}
};
end-goal
I am hoping I do not have to go over every file in our application and append .coffee to all require statements for coffee files if at all possible.
While this solution is not specific to coffee-loader, it did resolve my issue. I needed to add a resolve object to my configuration:
const path = require('path');
const webpack = require('webpack')
module.exports = {
entry: {
main: './src/main.coffee'
// other: './src/index2.js'
},
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'dist')
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: 'common' // Specify the common bundle's name.
})
],
module: {
rules: [
{
test: /\.coffee$/,
use: [
{
loader: 'coffee-loader',
options: { sourceMap: true }
}
]
}
]
},
resolve: {
extensions: [ '.coffee', '.js' ]
}
};
src - https://github.com/webpack-contrib/coffee-loader/issues/36