How to create a svg sprite on Laravel MIX? - laravel

I need to configure the build SVG sprites on laravel mix.
I tried several libraries under webpack, result = 0.
Can someone advise how to configure?
Where to write the handler code in webpack.mix.js or app.js?

One way I was able to get SVG sprites working with Laravele Mix & svg-spritemap-webpack-plugin.
First install the spritemap plugin
npm install svg-spritemap-webpack-plugin --save-dev
Then add config webpack.mix.js like that:
const mix = require('laravel-mix');
const SVGSpritemapPlugin = require('svg-spritemap-webpack-plugin');
// Set up the spritemap plugin
mix.webpackConfig({
plugins: [
new SVGSpritemapPlugin({
src:'assets/svg/icons/*.svg',
filename: '/svg/icons.svg',
prefix: '',
svg4everybody: true,
svgo: {
removeTitle: true,
removeStyleElement: true,
cleanupNumericValue: true,
},
})
]
});
// Adapt laravel-mix webpack config to better handle svg images.
Mix.listen('configReady', (webpackConfig) => {
// Add separate svg loader
webpackConfig.module.rules.push({
test: /\.(svg)$/,
include: /assets\/svg/,
loaders: [
{
loader: 'file-loader',
options: {
name: 'svg/[name].[ext]?[hash]',
publicPath: Config.resourceRoot
}
},
{
loader: 'img-loader',
options: Config.imgLoaderOptions
}
]
});
// Exclude local 'svg' folder from font loader
let fontLoaderConfig = webpackConfig.module.rules.find(rule => String(rule.test) === String(/\.(woff2?|ttf|eot|svg|otf)$/))
fontLoaderConfig.exclude = /(assets\/svg)/;
});
With this You should be able to add *.svg files into /resources/assets/svg/*.svg that are copied to public and get an svg sprite made from /resources/assets/svg/icons/*.svg

Related

How to add custom plugin in CKEditor 5 on Laravel Vue 2

How to add a custom plugin, more specifically the Inline widget plugin as mentioned in the example of the documentation of CKEditor in vue CKEditor ?
I have tried to follow the CKEditor setup process using CKEditor from source.
Since Laravel Vue doesn't have vue.config.js i have copied the same code on webpack.mix.js. Initially it failed to complied with an error
Module not found: Error: Can't resolve './#ckeditor/ckeditor5-ui/theme/mixins/_rwd.css' in '
But after removing some of the plugins such as `LinkPlugin, it complies but it run into another error
app.js?id=00c39e33120645d3026e:82180 TypeError: Cannot read properties of null (reading 'getAttribute')
at IconView._updateXMLContent (app.js?id=00c39e33120645d3026e:63098)
at IconView.render (app.js?id=00c39e33120645d3026e:63074)
at IconView.<anonymous> (app.js?id=00c39e33120645d3026e:80777)
at IconView.fire (app.js?id=00c39e33120645d3026e:78186)
at IconView.<computed> [as render] (app.js?id=00c39e33120645d3026e:80781)
at ViewCollection._renderViewIntoCollectionParent (app.js?id=00c39e33120645d3026e:72022)
at ViewCollection.<anonymous> (app.js?id=00c39e33120645d3026e:71883)
at ViewCollection.fire (app.js?id=00c39e33120645d3026e:78186)
at ViewCollection.addMany (app.js?id=00c39e33120645d3026e:74031)
at ViewCollection.add (app.js?id=00c39e33120645d3026e:73996)
Same issue as mentioned here
https://github.com/ckeditor/ckeditor5-vue/issues/24#issuecomment-947333698
But this solution didn't work for me.
Here is my complete webpack.mix.js file
let mix = require('laravel-mix');
/*
|--------------------------------------------------------------------------
| Mix Asset Management
|--------------------------------------------------------------------------
|
| Mix provides a clean, fluent API for defining some Webpack build steps
| for your Laravel application. By default, we are compiling the Sass
| file for the application as well as bundling up all the JS files.
|
*/
mix.js('resources/assets/js/app.js', 'public/js')
.sass('resources/assets/sass/app.scss', 'public/css')
.version();
const path = require('path');
const CKEditorWebpackPlugin = require('#ckeditor/ckeditor5-dev-webpack-plugin');
const {styles} = require('#ckeditor/ckeditor5-dev-utils');
module.exports = {
// The source of CKEditor is encapsulated in ES6 modules. By default, the code
// from the node_modules directory is not transpiled, so you must explicitly tell
// the CLI tools to transpile JavaScript files in all ckeditor5-* modules.
transpileDependencies: [
/ckeditor5-[^/\\]+[/\\]src[/\\].+\.js$/,
],
configureWebpack: {
plugins: [
// CKEditor needs its own plugin to be built using webpack.
new CKEditorWebpackPlugin({
// See https://ckeditor.com/docs/ckeditor5/latest/features/ui-language.html
language: 'en',
// Append translations to the file matching the `app` name.
translationsOutputFile: /app/
})
]
},
// Vue CLI would normally use its own loader to load .svg and .css files, however:
// 1. The icons used by CKEditor must be loaded using raw-loader,
// 2. The CSS used by CKEditor must be transpiled using PostCSS to load properly.
chainWebpack: config => {
// (1.) To handle editor icons, get the default rule for *.svg files first:
const svgRule = config.module.rule('svg');
// More rule
const filesRuleIndex = config.module.rules.findIndex(item => {
return item.test.test('.svg')
})
if (filesRuleIndex !== -1) {
config.module.rules[filesRuleIndex].test = /\.(png|jpe?g|gif|webp)$/
const svgRule = {...config.module.rules[filesRuleIndex]}
svgRule.test = /\.svg/
svgRule.exclude = svgRule.exclude || []
svgRule.exclude.push(path.join(__dirname, 'node_modules', '#ckeditor'))
config.module.rules.push(svgRule)
}
config.module.rules.push({
test: /ckeditor5-[^/\\]+[/\\]theme[/\\]icons[/\\][^/\\]+\.svg$/,
use: ["raw-loader"]
})
// Then you can either:
//
// * clear all loaders for existing 'svg' rule:
//
// svgRule.uses.clear();
//
// * or exclude ckeditor directory from node_modules:
svgRule.exclude.add(path.join(__dirname, 'node_modules', '#ckeditor'));
// Add an entry for *.svg files belonging to CKEditor. You can either:
//
// * modify the existing 'svg' rule:
//
// svgRule.use( 'raw-loader' ).loader( 'raw-loader' );
//
// * or add a new one:
config.module
.rule('cke-svg')
.test(/ckeditor5-[^/\\]+[/\\]theme[/\\]icons[/\\][^/\\]+\.svg$/)
.use('raw-loader')
.loader('raw-loader');
// (2.) Transpile the .css files imported by the editor using PostCSS.
// Make sure only the CSS belonging to ckeditor5-* packages is processed this way.
config.module
.rule('cke-css')
.test(/ckeditor5-[^/\\]+[/\\].+\.css$/)
.use('postcss-loader')
.loader('postcss-loader')
.tap(() => {
return styles.getPostCssConfig({
themeImporter: {
themePath: require.resolve('#ckeditor/ckeditor5-theme-lark'),
},
minify: true
});
});
},
};
Can anyone please tell me what is the proper way of setting this CKEditor to work with custom plugins
And my vue component script is like this
import CKEditor from '#ckeditor/ckeditor5-vue2';
import ClassicEditor from '#ckeditor/ckeditor5-editor-classic/src/classiceditor';
import EssentialsPlugin from '#ckeditor/ckeditor5-essentials/src/essentials';
import BoldPlugin from '#ckeditor/ckeditor5-basic-styles/src/bold';
import ItalicPlugin from '#ckeditor/ckeditor5-basic-styles/src/italic';
//import LinkPlugin from '#ckeditor/ckeditor5-link/src/link';
import ParagraphPlugin from '#ckeditor/ckeditor5-paragraph/src/paragraph';
//Custom Plugin same as in the documentation mentioned above,
//import Placeholder from "../../editor-plugins/Placeholder"; // Commented out
export default {
name: "AddEditDocuments",
props: {},
components:{
ckeditor: CKEditor.component
},
data() {
return {
editor: ClassicEditor,
editorData: '',
editorConfig: {
plugins: [
EssentialsPlugin,
BoldPlugin,
ItalicPlugin,
// LinkPlugin,
ParagraphPlugin
],
toolbar: {
items: [
'bold',
'italic',
'link',
'undo',
'redo'
]
}
},\
}
Packages:
Laravel : 8.76.1
Vue 2
CKEditor 5
Dont use CKEditor5 as it has some bugs in its editor just because of this i was also switch to CKEditor 4. After installing CKeditor using npm use it in the component. No need to configure it globally.
<template>
<ckeditor v-model="obj[name]" :config="editorConfig" ></ckeditor>
</template>
<script>
import CKEditor from 'ckeditor4-vue';
export default {
name: "Ckeditor",
props: {
obj: {
type: Object,
required: true,
},
name: {
type: String,
required: true,
}
},
components: {
ckeditor: CKEditor.component
},
data(){
return {
editorConfig: {
toolbar: [
[
'Bold',
'Italic',
'Link',
'BulletedList',
'NumberedList',
'Undo',
'Redo',
]
],
removePlugins: 'elementspath',
extraPlugins: 'filebrowser,uploadimage',
height: 100,
resize_enabled:false,
}
}
}
}
</script>
<style scoped>
</style>

Laravel mix webpack - Ignore locales when importing Moment.js

I would like to load 2 locales en-gb and fr-ch only from Moment.js , then assign the moment class to the scopewindow to use the library everywhere in my Vuejs components.
Currently, my app.js has this require line:
window.moment = require('moment')
I am suspecting it can be accomplished thanks to the solutions here (adding IgnorePlugin and ContextReplacementPlugin to webpack.config.js):
plugins.push(new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /en-gb|fr-ch/))
module.exports.plugins = plugins;
OR
plugins.push(new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/))
module.exports.plugins = plugins;
Where should you add these pieces of code (webpack.config.js and/or app.js and/or webpack.mix.js) to ignore all other locales when importing momentjs?
mix.webpackConfig({
plugins: [
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)
]
})
Source: https://laracasts.com/discuss/channels/elixir/laravel-mix-prevent-momentjs-locales
mix.webpackConfig( webpack => {
plugins: [
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)
]
});
this way you dont have to import webpack on the top of your file, which sometimes can cause errors.
and you also can put other necessary options like this
mix.webpackConfig( webpack => {
plugins: [
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)
],
resolve: {
extensions: ['.js', '.vue'],
alias: {
'#': __dirname + '/resources',
'#root': __dirname,
'#pages': __dirname + '/resources/js/pages'
},
fallback: { "path": false },
},
});

"transform-es3-member-expression-literals" usage in webpack 1.x

I am working on application that needs to be run on IE 8 enterprise version.I am getting following errors in the console:
Expected identifier : ;
indexOf is not available for the object.
For solving this I read this question on stackoverflow:
Babel 6.0.20 Modules feature not work in IE8
It suggests
transform-es3-member-expression-literals
transform-es3-property-literals
to be added.
But using this in webpack is not mentioned any where,not on babel official site.
Can anyone suggest the way how can I use it as a plugin to my project.
Note:I have already tried doing
var es3MemberExpressionLiterals = require('babel-plugin-transform-es3-member-expression-literals');
var es3PropertyLiterals = require('babel-plugin-transform-es3-property-literals');
plugins = [// Plugins for Webpack
new webpack.optimize.UglifyJsPlugin({minimize: false}),
new HtmlWebpackPlugin({
template: 'index.html', // Move the index.html file...
minify: { // Minifying it while it is parsed using the following, self–explanatory options
removeComments: false,
collapseWhitespace: false,
removeRedundantAttributes: false,
useShortDoctype: false,
removeEmptyAttributes: false,
removeStyleLinkTypeAttributes: false,
keepClosingSlash: true,
minifyJS: false,
minifyCSS: true,
minifyURLs: false
}
})
new es3MemberExpressionLiterals(),
new es3PropertyLiterals()
];
I've created a demo repository on github to show the full configuration by an example.
To get the two plugins running create a .babelrc file, with the following content
{
"plugins": [
"transform-es3-member-expression-literals",
"transform-es3-property-literals"
]
}
In the standard configuration babel-loader in your webpack.config.js babel takes a look into the .babelrc to configure plugins.
// webpack.config.js (partial code only)
module: {
loaders: [
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
}
]
}
If everything is set up correctly webpack should transform the following code
// src/main.js
var foo = { catch: function() {} };
console.log(foo.catch)
into
// bundle.js
/* 0 */
/***/ function(module, exports) {
var foo = { "catch": function () {} };
console.log(foo["catch"]);
/***/ }
See also the examples for the plugins: babel-plugin-transform-es3-property-literals and babel-plugin-transform-es3-member-expression-literals.
The question you link to is about Babel plugins, and you are trying to pass them as Webpack plugins. You'd need to set up Babel as a loader for your application and pass the plugins to that. Merge the following into your Webpack configuration.
module: {
loaders: [{
loader: 'babel',
test: /\.js$/,
exclude: /node_modules/,
plugins: [
'babel-plugin-transform-es3-member-expression-literals',
'babel-plugin-transform-es3-property-literals',
],
}],
},

Webpack, sass being overwriten

I'll start by saying I have a bit of a bizarre webpack build. I have 2 projects, the main project and the shared project (like a common library).
Whenever I refer to my shared project from the main project, it get some bizarre IE only/react/webpack build error where I get an error when trying to refer to my shared library. To solve this, I aliased my shared library references to the actual source on my computer in a different folder. That looks something like this:
var alias.shared-library = 'c:\\shared-library\\index.js';
This fixed my bizarre IE problem. However, another issue raised in my webpack production build. On the production server, the shared library exists within the node_modules folder, so I tried something like this:
var alias.shared-library = 'node_modules\\shared-library\\index.js';
It mostly works, except all my scss from the main project is overwritten by scss from the shared project (the output css only contains scss from the shared lib and not main). My full setup looks something like this (I removed parts I thought weren't important):
var SHARED_PATH = path.resolve(__dirname, 'node_modules/shared-library');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const extractCss = new ExtractTextPlugin('css.styles.css');
const extractScss = new ExtractTextPlugin('scss.styles.css');
const plugs = [];
plugs.push(
new webpack.DefinePlugin({
__DEVELOPMENT__: false
})
);
plugs.push(
new HtmlWebpackPlugin({
template: './index.html',
inject: 'body',
chunks: ['app', 'vendor']
})
);
plugs.push(new webpack.NoErrorsPlugin());
plugs.push(
new CopyWebpackPlugin([
{ from: 'src/assets', to: 'assets' },
])
);
plugs.push(
new SplitByPathPlugin([
{ name: 'vendor', path: [path.join(__dirname, 'node_modules')] },
])
);
plugs.push(extractCss);
plugs.push(extractScss);
plugs.push(
new webpack.optimize.UglifyJsPlugin({
sourceMap: true,
compress: {
warnings: false
}
})
);
var alias = {
'shared-library': path.resolve(SHARED_PATH, '\\src\\index.js')
};
var loaderDirs = ['node_modules', 'webpack_loaders'];
var moduleDirs = ['node_modules', 'src'];
loaderDirs.push(SHARED_PATH + '\\node_modules');
moduleDirs.push(SHARED_PATH + '\\node_modules');
moduleDirs.push(SHARED_PATH + '\\src');
module.exports = {
entry: {
app: ['./src/index.js']
},
resolve: {
extensions: ['', '.js', '.scss', '.css'],
modulesDirectories: moduleDirs,
alias
},
resolveLoader: {
modulesDirectories: loaderDirs
},
output: {
path: path.join(__dirname, 'dist'),
filename: '[name].[hash].js',
publicPath: '/main/',
sourceMapFilename: '[name].[hash].js.map',
chunkFilename: '[id].chunk.js',
},
plugins: plugs,
module: {
loaders: [
{
test: /\.js?$/,
loader: 'babel?sourceMaps=true',
include: [/src/, path.resolve(SHARED_PATH, '\\src\\index.js')]
},
{
test: /\.css$/,
loader: extractCss.extract('style', 'css')
},
{
test: /\.scss$/,
loader: extractScss.extract('style', 'css!sass'),
include: /src/ // Trying to exclude scss from shared-library, doesn't work though
},
loaders.json,
loaders.image,
loaders.svg,
loaders.font,
loaders.locale,
loaders.html
]
},
postcss: (webpack) => {
return [
autoprefixer({
browsers: ['last 2 versions'],
}),
postcssImport({
addDependencyTo: webpack,
})
];
},
externals: {
'react/lib/ReactContext': 'window',
'react/lib/ExecutionEnvironment': 'window',
'react/addons': true
}
};
I've tried things like different permutations of exclude/include on my loaders. I thought the allChunks option on ExtractTextPlugin might work:
const extractScss = new ExtractTextPlugin({filename: 'scss.styles.css', allChunks: true});
but it just gives me this error:
TypeError: path.replace is not a function
at Template.replacePathVariables (c:\r2\RCA\rca-ui\node_modules\webpack\lib\
TemplatedPathPlugin.js:70:4)
at Template.applyPlugins [as applyPluginsWaterfall] (c:\r2\RCA\rca-ui\node_m
odules\webpack\node_modules\tapable\lib\Tapable.js:37:47)
at Compilation.getPath (c:\r2\RCA\rca-ui\node_modules\webpack\lib\Compilatio
n.js:882:27)
at ExtractTextPlugin.<anonymous> (c:\r2\RCA\rca-ui\node_modules\extract-text
-webpack-plugin\index.js:300:29)
at Array.forEach (native)
at ExtractTextPlugin.<anonymous> (c:\r2\RCA\rca-ui\node_modules\extract-text
-webpack-plugin\index.js:289:20)
at Compilation.next (c:\r2\RCA\rca-ui\node_modules\webpack\node_modules\tapa
ble\lib\Tapable.js:69:14)
at ExtractTextPlugin.<anonymous> (c:\r2\RCA\rca-ui\node_modules\extract-text
-webpack-plugin\index.js:309:4)
at Compilation.applyPluginsAsync (c:\r2\RCA\rca-ui\node_modules\webpack\node
_modules\tapable\lib\Tapable.js:71:13)
at Compilation.<anonymous> (c:\r2\RCA\rca-ui\node_modules\webpack\lib\Compil
ation.js:563:8)
at Compilation.next (c:\r2\RCA\rca-ui\node_modules\webpack\node_modules\tapa
ble\lib\Tapable.js:67:11)
at ExtractTextPlugin.<anonymous> (c:\r2\RCA\rca-ui\node_modules\extract-text
-webpack-plugin\index.js:285:5)
at c:\r2\RCA\rca-ui\node_modules\extract-text-webpack-plugin\node_modules\as
ync\lib\async.js:52:16
at done (c:\r2\RCA\rca-ui\node_modules\extract-text-webpack-plugin\node_modu
les\async\lib\async.js:246:17)
at c:\r2\RCA\rca-ui\node_modules\extract-text-webpack-plugin\node_modules\as
ync\lib\async.js:44:16
at c:\r2\RCA\rca-ui\node_modules\extract-text-webpack-plugin\index.js:269:6
at c:\r2\RCA\rca-ui\node_modules\extract-text-webpack-plugin\node_modules\as
ync\lib\async.js:52:16
at done (c:\r2\RCA\rca-ui\node_modules\extract-text-webpack-plugin\node_modu
les\async\lib\async.js:246:17)
at c:\r2\RCA\rca-ui\node_modules\extract-text-webpack-plugin\node_modules\as
ync\lib\async.js:44:16
at c:\r2\RCA\rca-ui\node_modules\extract-text-webpack-plugin\index.js:259:9
at c:\r2\RCA\rca-ui\node_modules\webpack\lib\Compilation.js:469:4
at Array.forEach (native)
at callback (c:\r2\RCA\rca-ui\node_modules\webpack\lib\Compilation.js:468:14
)
at Compilation.<anonymous> (c:\r2\RCA\rca-ui\node_modules\webpack\lib\Compil
ation.js:489:4)
at c:\r2\RCA\rca-ui\node_modules\webpack\lib\Compilation.js:332:10
at c:\r2\RCA\rca-ui\node_modules\webpack\node_modules\async\lib\async.js:52:
16
at Object.async.forEachOf.async.eachOf (c:\r2\RCA\rca-ui\node_modules\webpac
k\node_modules\async\lib\async.js:236:30)
at Object.async.forEach.async.each (c:\r2\RCA\rca-ui\node_modules\webpack\no
de_modules\async\lib\async.js:209:22)
at Compilation.addModuleDependencies (c:\r2\RCA\rca-ui\node_modules\webpack\
lib\Compilation.js:185:8)
at Compilation.processModuleDependencies (c:\r2\RCA\rca-ui\node_modules\webp
ack\lib\Compilation.js:170:7)
Any ideas on the proper approach to solve this problem? Would the allChunks option help me here? Do I need to tighten up my include/excludes? Is there something else I'm missing? Should I give up and try and fix the IE problem another way? Is there a way I can debug what is happening? Here's the versions of the libraries I am using:
"extract-text-webpack-plugin": "1.0.1",
"style-loader": "0.13.0",
"sass-loader": "3.1.2",
"webpack": "1.13.2"
Thanks

Error when combining sass-loader with css-modules

I'm getting the following error when using SASS's map-get.
ERROR in ./src/special.scss
Module build failed: ModuleBuildError: Module build failed: Unknown word (11:14)
9 |
10 | #mixin mediaquery($name) {
> 11 | #media #{map-get($breakpoints, $name)} {
| ^
12 | #content;
13 | }
14 | }
This is only happening when I use both the sass-loader and another loader.
I first thought this was caused by the PostCSS Loader, but it seems like it's the sass-loading causing problems and not transforming the scss when using css-modules.
I've created a sample repo illustrating the problem: https://github.com/tiemevanveen/sass-css-components-fail-example.
You can use the different branches to test:
master: CSS Modules + SASS
postcss CSS Modules + SASS + PostCSS
log-source: Uses CSS modules + SASS + Custom source logging module
no-css-modules: SASS + Custom source logging module
Only the first and the last branch run without errors.
I've created the log-source example to see what the sass-loader is returning and it looks like it's not transforming the sass (but this might also be me misinterpreting how the loaders work).
The other example without css modules does show the right transformed code..
I'm puzzled why the master branch (without postcss or another custom loader) is working fine though.. if something would be wrong with the sass-loader then that one should also fail right?
I've filed an issue, but I'm thinking this has more chance on StackOverflow since it's such a specific problem and might be more a config problem. Here's my webpack config:
const webpack = require('webpack');
const path = require('path');
const autoprefixer = require('autoprefixer');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const WriteFilePlugin = require('write-file-webpack-plugin');
module.exports = {
devtool: 'source-source-map',
debug: true,
context: path.resolve(__dirname, './src'),
entry: {
app: './index.js'
},
output: {
path: path.resolve(__dirname, './static'),
filename: '[name].js',
publicPath: '/static/'
},
devServer: {
outputPath: path.resolve(__dirname, './static'),
},
plugins: [
new webpack.NoErrorsPlugin(),
new ExtractTextPlugin('[name].css'),
new WriteFilePlugin()
],
module: {
loaders: [
{
test: /\.scss$/,
loader: ExtractTextPlugin.extract('style-loader', [
'css?modules&importLoaders=1&localIdentName=[path]_[name]_[local]',
// 'postcss-loader',
'sass'
])
},
// + js loader
]
},
postcss: [
autoprefixer({ browsers: ['> 0.5%'] })
],
resolveLoader: {
fallback: [
path.resolve(__dirname, 'loaders'),
path.join(process.cwd(), 'node_modules')
]
},
resolve: {
extensions: ['', '.js', '.json'],
}
};
You need to increase the importLoaders query parameter as you add loaders. That feature is poorly documented and confusing, but in your samples repo, importLoaders=2 with both Sass and PostCSS works.

Resources