Module parse failed: Unexpected character '#' when exporting Swiper styles - javascript

When exporting styles from the Swiper library ( import 'swiper/css'; ), I catch that error, no problem with swiper.js export. I've seen articles explaining how to solve this problem for webpack, where you need to add the following code to webpack.config.js:
{
test: /\.(sass|less|css)$/,
use: ["style-loader", "css-loader", 'sass-loader'],
}
But, the problem is that I use gulp build and don't know the analogue of this file for my build, where exactly to insert this code so as not to disrupt the work of the build itself? If it helps, I'm using the gulp build by Фрилансер по жизни.
Files where the code is supposed to be inserted:
SCSS.JS:
import dartSass from 'sass';
import gulpSass from 'gulp-sass';
import rename from 'gulp-rename';
import cleanCss from 'gulp-clean-css'; // Сжатие CSS файла
import webpcss from 'gulp-webpcss'; // Вывод WEBP изображений
import autoprefixer from 'gulp-autoprefixer'; // Добавление вендорных префиксов
import groupCssMediaQueries from 'gulp-group-css-media-queries'; // Групировка медиа запросов
const sass = gulpSass(dartSass);
export const scss = () => {
return app.gulp.src(app.path.src.scss, { sourcemaps: app.isDev })
.pipe(app.plugins.plumber(
app.plugins.notify.onError({
title: "SCSS",
message: "Error: <%= error.message %>"
})))
.pipe(sass({
outputStyle: 'expanded'
}))
.pipe(app.plugins.replace(/#img\//g, '../img/'))
.pipe(
app.plugins.if(
app.isBuild,
groupCssMediaQueries()
)
)
.pipe(
app.plugins.if(
app.isBuild,
autoprefixer({
grid: true,
overrideBrowserslist: ["last 3 versions"],
cascade: true
})
)
)
.pipe(
app.plugins.if(
app.isBuild,
webpcss(
{
webpClass: ".webp",
noWebpClass: ".no-webp"
}
)
)
)
.pipe(app.gulp.dest(app.path.build.css))
.pipe(
app.plugins.if(
app.isBuild,
cleanCss()
)
)
.pipe(rename({
extname: ".min.css"
}))
.pipe(app.gulp.dest(app.path.build.css))
.pipe(app.plugins.browsersync.stream());
}
JS.JS:
import webpack from "webpack-stream";
export const js = () => {
return app.gulp.src(app.path.src.js, { sourcemaps: app.isDev })
.pipe(app.plugins.plumber(
app.plugins.notify.onError({
title: "JS",
message: "Error: <%= error.message %>"
}))
)
.pipe(webpack({
mode: app.isBuild ? 'production' : 'development',
output: {
filename: 'app.min.js',
}
}))
.pipe(app.gulp.dest(app.path.build.js))
.pipe(app.plugins.browsersync.stream());
}
If you need more information, please let me know, thanks in advance!

Related

Replace all image paths in a css file with base64 encoded strings - rollup

I am trying to replace all the image paths in a css background url to a base64 encoded string while doing a rollup build.
I am using rollup-plugin-postcss for this, I am able to generate a separate .css file in the build, but I want the image paths to be replaced with base64 encoded data URL.
Something like this:
background: url('images/sample.png');
to
background: url('data:image/png;base64,R0lGODlhyAAiALM...DfD0QAADs=');
Here is what I have been doing:
import postcss from 'rollup-plugin-postcss'
...
plugins: [
postcss({
extensions: ['.css'],
extract: path.resolve('dist/index.css'),
}),
]
A possible solution would be to use postcss-url:
import postcssurl from 'postcss-url';
postcss({
..., // postcss options
plugins: [
postcssurl({
url: 'inline',
}),
],
}),
I am not not sure if it is possible with rollup-plugin-postcss, Try using “image-to-base64” npm it’s very simple,
Download command :
npm i -S image-to-base64
Example :
const imageToBase64 = require('image-to-base64');
//or
//import imageToBase64 from 'image-to-base64/browser';
imageToBase64("path/to/file.jpg") // Path to the image
.then(
(response) => {
console.log(response); // "cGF0aC90by9maWxlLmpwZw=="
}
)
.catch(
(error) => {
console.log(error); // Logs an error if there was one
}
)
There is more examples here
https://www.npmjs.com/package/image-to-base64
If you need more help you can reply to this comment.
You can use postcss-inline-base64
Here is a working example based on this rollup starter:
import resolve from '#rollup/plugin-node-resolve';
import commonjs from '#rollup/plugin-commonjs';
import { terser } from 'rollup-plugin-terser';
import path from 'path'
import postcss from 'rollup-plugin-postcss'
import base64Inliner from 'postcss-inline-base64'
// `npm run build` -> `production` is true
// `npm run dev` -> `production` is false
const production = !process.env.ROLLUP_WATCH;
const __dirname = path.resolve();
const baseDir = path.join(__dirname, 'public')
export default {
input: 'src/main.js',
output: {
file: 'public/bundle.js',
format: 'iife', // immediately-invoked function expression — suitable for <script> tags
sourcemap: true
},
plugins: [
postcss({
extensions: ['.css'],
extract: path.resolve('public/styles.css'),
plugins: [base64Inliner({ baseDir })]
}),
...
]
};
I then created a css file in the src folder:
body {
background: url('b64---./images/test.png---');
}
In index.js:
import "./styles.css";
In index.html
....
<title>rollup-starter-app</title>
<link href="styles.css" rel="stylesheet" />
....
I was able to get:

Rollup + Typescript + ESLint wrong warning

I created a project using Rollup which use Typescript and ESLint with the typescript-eslint plugin and it seems that ESLint is executed on compiled code.
Here is my Rollup config :
export default commandLineArgs => {
const serving = commandLineArgs.configServe === true;
return {
input: 'src/main.ts',
output: {
file: pkg.main,
format: 'umd',
name: 'bot',
sourcemap: !isProduction
},
plugins: [
eslint({ include: ['src/**/*.js', 'src/**/*.ts'] }),
nodeResolve(),
commonjs(),
typescript({ sourceMap: !isProduction, inlineSources: !isProduction }),
replace({
'process.env.NODE_ENV': JSON.stringify(isProduction ? 'production' : 'development')
}),
scss({
includePaths: ['node_modules/'],
outputStyle: isProduction ? 'compressed' : 'expanded'
}),
html({ include: 'src/**/*.html' }), // to allow import of html files (for templating)
image(), // to allow import of image files
isProduction && terser(),
isProduction && filesize(),
serving && serve({
open: true,
openPage: '/index.html',
contentBase: ['demo', 'dist'],
})
]
}
}
Here is my main.ts :
import './styles/app.scss';
import ChatUI from './ui';
import Chat from './chat';
export default async function init(target: HTMLDivElement): Promise<Chat> {
const ui = new ChatUI(target);
const chat = new Chat(ui);
return chat;
}
And this is what ESLint logs :
.../src/main.ts
4:16 warning Missing return type on function #typescript-eslint/explicit-module-boundary-types
4:36 warning Argument 'target' should be typed #typescript-eslint/explicit-module-boundary-types
As you can see, both line numbers and errors are wrong, as if it use the generated js file rather than the ts source. What is the problem here ?
It appears that the "official" version, #rollup/plugin-eslint, is outdated, and uses an old version of eslint. There are two available alternatives that are more current: #rbnlffl/rollup-plugin-eslint and rollup-plugin-eslint2. The former did the trick for me; I haven't tried the latter.

Rollup.js - Use rollup.config.js in JS API?

I have a working rollup.config.js file but need to run a separate packaging script after Rollup is done. My plan was to use Rollup's watchers via their JS API. However, I cannot get the JS API to work at all.
I am referencing this code from the Rollup site...
const loadConfigFile = require('rollup/dist/loadConfigFile');
const path = require('path');
const rollup = require('rollup');
loadConfigFile(path.resolve(__dirname, 'rollup.config.js'))
.then(async ({options, warnings}) => {
warnings.flush();
const bundle = await rollup.rollup(options);
await Promise.all(options.output.map(bundle.write));
rollup.watch(options);
})
but I keep getting an error Unknown input options: 0.......Error: You must supply options.input to rollup
My rollup.config.js is as follow...
import svelte from 'rollup-plugin-svelte';
import resolve from '#rollup/plugin-node-resolve';
import commonjs from '#rollup/plugin-commonjs';
import livereload from 'rollup-plugin-livereload';
import { terser } from "rollup-plugin-terser";
import replace from '#rollup/plugin-replace';
import json from '#rollup/plugin-json';
const production = !process.env.ROLLUP_WATCH;
export default {
input: 'src/main.js',
output: {
sourcemap: true,
format: 'iife',
name: 'app',
file: 'public/bundle.js'
},
plugins: [
json(),
production && replace({
'eruda': ``,
exclude: 'node_modules/**',
delimiters: ['import * as eruda from \'', '\'']
}),
production && replace({
'eruda': ``,
exclude: 'node_modules/**',
delimiters: ['', '.init()']
}),
svelte({
dev: !production,
css: css => {
css.write('public/bundle.css');
}
}),
resolve({ browser: true }),
commonjs(),
!production && livereload('public'),
production && terser()
],
watch: {
clearScreen: false
}
};
Any thoughts are appreciated!
I think the example at rollupjs.org is wrong. Shouldn't it be like this instead?
const loadConfigFile = require('rollup/dist/loadConfigFile')
const path = require('path')
const rollup = require('rollup')
// load the config file next to the current script;
// the provided config object has the same effect as passing "--format es"
// on the command line and will override the format of all outputs
loadConfigFile(path.resolve(__dirname, 'rollup.config.js'), {format: 'es'})
.then(({options, warnings}) => {
// "warnings" wraps the default `onwarn` handler passed by the CLI.
// This prints all warnings up to this point:
console.log(`We currently have ${warnings.count} warnings`)
// This prints all deferred warnings
warnings.flush()
// options is an "inputOptions" object with an additional "output"
// property that contains an array of "outputOptions".
// The following will generate all outputs and write them to disk the same
// way the CLI does it:
options.map(async options => {
const bundle = await rollup.rollup(options)
await Promise.all(options.output.map(bundle.write))
// You can also pass this directly to "rollup.watch"
rollup.watch(options)
})
})
Figured it out, apparently the options returned from loadConfigFile is an array so I had to do options[0] inside the async function

Require doesn't appear in my code, but webpack keeps throwing the error "require is not defined."

I'm writing an electron app with react. I run the developement version using this command:
webpack-dev-server --hot --host 0.0.0.0 --port 4000 --config=./webpack.dev.config.js
Here is the webpack.dev.config.js file
const webpack = require('webpack');
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { spawn } = require('child_process');
const helpers = require('./config/helpers');
// Config directories
const SRC_DIR = path.resolve(__dirname, 'src');
const OUTPUT_DIR = path.resolve(__dirname, 'dist');
// Any directories you will be adding code/files into, need to be added to this array so webpack will pick them up
const defaultInclude = [SRC_DIR];
module.exports = {
entry: SRC_DIR + '/index.js',
output: {
path: OUTPUT_DIR,
publicPath: '/',
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.css$/,
use: [{ loader: 'style-loader' }, { loader: 'css-loader' }],
include: defaultInclude
},
{
test: /\.jsx?$/,
use: [{ loader: 'babel-loader' }],
include: defaultInclude
},
{
test: /\.(jpe?g|png|gif)$/,
use: [{ loader: 'file-loader?name=img/[name]__[hash:base64:5].[ext]' }],
include: defaultInclude
},
{
test: /\.(eot|svg|ttf|woff|woff2)$/,
use: [{ loader: 'file-loader?name=font/[name]__[hash:base64:5].[ext]' }],
include: defaultInclude
}
]
},
target: 'electron-renderer',
plugins: [
new HtmlWebpackPlugin({
template: helpers.root('public/index.html'),
inject: 'body'
}),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('development')
})
],
devtool: 'cheap-source-map',
devServer: {
contentBase: OUTPUT_DIR,
stats: {
colors: true,
chunks: false,
children: false
},
setup() {
spawn(
'electron',
['.'],
{ shell: true, env: process.env, stdio: 'inherit' }
)
.on('close', code => {
console.error("electron exited with code ", code);
process.exit(0)
})
.on('error', spawnError => console.error(spawnError));
}
}
};
Once the electron browser opens it has the following error in the Dev-Tools console.
Uncaught ReferenceError: require is not defined
at Object.url (index.js:23)
at __webpack_require__ (bootstrap:709)
at fn (bootstrap:94)
at Object../node_modules/webpack-dev-server/client/utils/createSocketUrl.js (createSocketUrl.js:4)
at __webpack_require__ (bootstrap:709)
at fn (bootstrap:94)
at Object.<anonymous> (client:20)
at Object../node_modules/webpack-dev-server/client/index.js?http://0.0.0.0:4000 (client:176)
at __webpack_require__ (bootstrap:709)
at fn (bootstrap:94)
The place where it claims this is occurring is at index.js:23.
Here is the build version of index.js:
import React from "react";
import { render } from "react-dom";
import { Provider } from "react-redux";
import App from "./components/App";
import { createStore, applyMiddleware } from "redux";
import thunk from "redux-thunk";
import { ipcRenderer as ipc } from "electron";
import { onUpdate } from "./actions/workerActions";
import { RECEIVED_STATE } from "./actions/types";
import "./assets/css/index.css";
import rootReducer from "./reducers/rootReducer";
import defaultState from "../config/defaultstate"; //Setup redux store
const middleware = [thunk];
const store = createStore(rootReducer, defaultState, applyMiddleware(...middleware));
ipc.on(RECEIVED_STATE, arg => {
console.log("Recieved State: ", arg);
onUpdate(arg)(store.dispatch);
}); // Now we can render our application into it
render(React.createElement(Provider, {
store: store
}, React.createElement(App, null)), document.getElementById("app"));
As you can see require does not appear here and all of the import aside from ipcRender are designed to run client-side, and therefore should not use required. I tried commenting out the ipcRender import but it resulted in the exact same error.
Most puzzlingly of all, I get the exact same error even with the entire index.js file commented out. The console still claiming the block comment contains a reference to require, which is not defined.
If you're using webpack directly then make sure you have the following in the webpack config that targets your renderer code.
// webpack.config.js
...
module.exports = {
...
target: 'web',
...
}
If you're using Vue then you'll need something like the following:
// vue.config.js
...
module.exports = {
...
configureWebpack: {
target: 'web'
},
...
}
Or, in my case I was using vue-cli-plugin-electron-builder and so need the following:
// vue.config.js
...
module.exports = {
...
pluginOptions: {
electronBuilder: {
nodeIntegration: false,
chainWebpackRendererProcess: config => {
config.target('web');
}
}
},
...
}
It turns out that the error is caused by importing electron's ipcRenderer which requires node integration and uses require. The reason that commenting out the import in the index.js didn't fix the error was because it was imported in other files.

how to use TS+css+scss in react SSR framework next?

I'm am using TS + CSS + SCSS in nextJS. I will import some CSS files, but I want to set cssModule:false to those CSS files, then I will import my own SCSS files and set cssModule:true.
The below is my code in next.config.js, it transfers CSS files to module.
const withSass = require("#zeit/next-sass");
const withTypescript = require("#zeit/next-typescript");
const withCSS = require("#zeit/next-css");
module.exports = withTypescript(
withCSS(
withSass({
cssModules: true
})
)
);
Could you please advise me on the right approach of importing CSS files?
The configuration of next-css is global, you either using cssModules or not.
My solution for this was to configure webpack manually to not apply cssModules on files with .global.css suffix.
config.module.rules.forEach(rule => {
if (rule.test.toString().includes('.scss')) {
rule.rules = rule.use.map(useRule => {
if (typeof useRule === 'string') {
return {
loader: useRule,
};
}
if (useRule.loader.startsWith('css-loader')) {
return {
oneOf: [
{
test: /\.global\.scss$/,
loader: useRule.loader,
options: {
...useRule.options,
modules: false,
},
},
{
loader: useRule.loader,
options: useRule.options,
},
],
};
}
return useRule;
});
delete rule.use;
}
});
There is an open PR for next-css to include similar solution to the lib.

Categories