I am starting my first project with React.
To start with, I just have a single component LikeButton.tsx, which is injected into the body. I am trying to apply some styles to this button:
import './LikeButton.css';
LikeButton.css:
button {
color: red;
}
Here is my webpack.config.ts:
module.exports = {
module: {
rules: [
{
test: /\.(js|jsx|tsx|ts)$/,
exclude: /(node_modules|dist)/,
use: 'babel-loader'
}, {
test: /\.css$/i,
use: [
'style-loader', 'css-loader'
]
}
]
},
...
};
When I run webpack, I end up with the following error:
ERROR in src/components/LikeButton.css:1:7
[unknown]: Parsing error: ';' expected.
> 1 | button {
| ^
2 | color: red;
3 | }
The css syntax is correct, so I am guessing the css is being interpreted as javascript/typescript somewhere, but I cannot see where due to the [unknown]-part in the error message.
The loader
What is happening here?
Instead of removing ForkTsCheckerWebpackPlugin which of course you may need for typescript / React combination to work properly, specify the files that you want eslint to check
eslint: {
files: './src/**/*.{ts,tsx,js,jsx}',
},
this tells eslint to check javascript and typescript files only, thus removing the css error.
It was the Fork TS Checker Webpack Plugin that caused the issue. By removing it from module.exports.plugins in webpack.config.ts, the error disappeared:
module.exports = {
...
plugins: [
new ForkTsCheckerWebpackPlugin({
async: false,
eslint: {
files: "./src/**/*",
},
}),
new MiniCssExtractPlugin(),
],
}
...
Related
I am trying to open a sqlite3 database encrypted with sqlcipher. I have the password and I could open it successfully using sqlitebrowser.
I started my project using this template. It is based on the electron-forge webpack plugin.
When I type yarn start, it creates a .webpack folder and all the compiled code goes in it. When I stop the terminal command, this folder disappears.
Then I wanted to use the package #journeyapps/sqlcipher to open my database, but this line is causing an error in the main process: const sqlite3 = require("#journeyapps/sqlcipher")
The error is:
Error: Cannot find module '<<my_path>>/.webpack/main/native_modules/lib/binding/napi-v6-linux-x64/node_sqlite3.node'
The package documentation says two things about using it with electron-forge:
make sure that the folder node_modules/#journeyapps/sqlcipher/lib/binding/napi-v6-linux-x64 exists
-> yes it exists
Disable rebuilding of this library using the onlyModules option of electron-rebuild in your package.json "config": { "forge": { "electronRebuildConfig": { "onlyModules": [] // Specify other native modules here if required } }
-> I did it, I added the lines of code
I still have the error, but I feel it can be solved "easily" (with a lot more understanding of webpack than I have). Indeed, a solution would be to move the folder binding/napi-v6-linux-x64 into .webpack each time I launch the app, right?
I tried to do electron-rebuild -f -w sqlite3, the rebuild succeeded but nothing happens, I still have the same error.
I am stuck here and cannot go further for my app, as it lays on reading this database.
Should I start a new project and avoid using webpack? Do you have any example of a project where this package is successfully imported and used?
Thank you in advance for your help!
Well, I finally figured it out. Actually, I tried so much little changes but I managed to make the app work (nearly) as expected.
How I found the solution
First: this doesn't have anything to do with the library sqlcipher itself. In fact, it's a webpack configuration problem while dealing with native libraries.
I started a fresh minimal install of electron-forge with Webpack and Typescript template (npx create-electron-app test-electron-forge-github --template=typescript-webpack) and added sqlite3 and #journeyapps/sqlcipher. It worked so I made a lot of changes in my Webpack configuration to make it closer with the electron-forge one.
Warning
The changes I made broke Redux. I chose to sacrifice Redux in order to make sqlcipher work, as today I didn't find a solution for both of them to work.
Old Webpack configuration files
main.webpack.js
module.exports = {
resolve: {
extensions: ['.ts', '.js']
},
entry: './electron/main.ts',
module: {
rules: require('./rules.webpack'),
}
}
renderer.webpack.js
module.exports = {
resolve: {
extensions: ['.ts', '.tsx', '.js']
},
module: {
rules: require('./rules.webpack'),
},
}
rules.webpack.js
module.exports = [
{
test: /\.node$/,
use: 'node-loader',
},
{
test: /\.(m?js|node)$/,
parser: { amd: false },
use: {
loader: '#marshallofsound/webpack-asset-relocator-loader',
options: {
outputAssetBase: 'native_modules',
},
},
resolve: {
fullySpecified: false,
}
},
{
test: /\.(js|ts|tsx)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
}
},
{
test: /\.(png|jpe?g|gif)$/i,
loader: 'file-loader',
options: {
name: '[path][name].[ext]',
},
},
{
test: /\.(sass|less|css)$/,
use: [
'style-loader',
'css-loader',
'postcss-loader',
'sass-loader',
]
},
]
New configuration
main.webpack.js
module.exports = {
resolve: {
extensions: ['.ts', '.js']
},
entry: './electron/main.ts',
module: {
rules: [
...require('./rules.webpack'),
{
test: /\.(m?js|node)$/,
parser: { amd: true },
use: {
loader: '#vercel/webpack-asset-relocator-loader',
options: {
outputAssetBase: 'native_modules',
emitDirnameAll: true,
},
}
},
],
}
}
The native modules configuration has been moved from rules.webpack.js to main.webpack.js. This is due to a bug happening in the renderer process if the rule stayed in the rules.wepback.ts file.
The window would open but would stay blank. In the console, there would be an error: __dirname is not defined. See this Github issue from where I took the solution.
Also note that I changed the loader as the previous one was not doing properly its job.
renderer.webpack.js
Unchanged
rules.webpack.js
module.exports = [
{
// We are specifying native_modules in the test because the asset relocator loader generates a
// "fake" .node file which is really a cjs file.
test: /native_modules\/.+\.node$/,
use: 'node-loader',
},
{
test: /\.(js|ts|tsx)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
}
},
{
test: /\.(png|jpe?g|gif)$/i,
loader: 'file-loader',
options: {
name: '[path][name].[ext]',
},
},
{
test: /\.(sass|less|css)$/,
use: [
'style-loader',
'css-loader',
'postcss-loader',
'sass-loader',
]
},
]
Redux
I had to remove this property from rules.webpack.js:
resolve: {
fullySpecified: false,
}
This line was making Redux work.
Conclusion
I don't really know how this works, but it works. I hope it will help you if you are struggling as I was.
It seems like everything i'm finding online is old and doesn't seem to work for me.. Any help is appreciated.
I ran "npm run eject". Then I installed with NPM
"devDependencies": {
"less": "^3.12.2",
"less-loader": "^6.2.0"
},
and in my "webpack.config.js" file this is how i have it so far:
module: {
strictExportPresence: true,
rules: [
{
test: /\.less$/,
loader: 'less-loader', // compiles Less to CSS
},
// Disable require.ensure as it's not a standard language feature.
{ parser: { requireEnsure: false } },
// First, run the linter.
// It's important to do this before Babel processes the JS.
{
test: /\.(js|mjs|jsx|ts|tsx)$/,
enforce: 'pre',
use: [
{
options: {
cache: true,
formatter: require.resolve('react-dev-utils/eslintFormatter'),
eslintPath: require.resolve('eslint'),
resolvePluginsRelativeTo: __dirname,
},
loader: require.resolve('eslint-loader'),
},
],
include: paths.appSrc,
},
and then i get this error message when trying to run:
Failed to compile ./src/styles/index.less
(./node_modules/css-loader/dist/cjs.js!./node_modules/less-loader/dist/cjs.js!./node_modules/file-loader/dist/cjs.js??ref--7-oneOf-7!./src/styles/index.less)
module.exports = webpack_public_path +
"static/media/index.1f54121a.less";
^ Unrecognised input
Error in G:\Work Projects\uno\src\styles\index.less (line 1, column 15)
Hopefully this helps someonme. I found the answer here: https://segmentfault.com/a/1190000018858055
Short Version:
const cssRegex = /\.(css|less)$/;
const cssModuleRegex = /\.module\.(css|less)$/;
...
...
...
// "postcss" loader applies autoprefixer to our CSS.
// "css" loader resolves paths in CSS and adds assets as dependencies.
// "style" loader turns CSS into JS modules that inject <style> tags.
// In production, we use MiniCSSExtractPlugin to extract that CSS
// to a file, but in development "style" loader enables hot editing
// of CSS.
// By default we support CSS Modules with the extension .module.css
{
test: cssRegex, // edited to add less above
exclude: cssModuleRegex, // edited to add less above
use: getStyleLoaders({
importLoaders: 2, // changed from 1 to 2
modules: true, // added this line
sourceMap: isEnvProduction && shouldUseSourceMap,
},
'less-loader'),
// Don't consider CSS imports dead code even if the
// containing package claims to have no side effects.
// Remove this when webpack adds a warning or an error for this.
// See https://github.com/webpack/webpack/issues/6571
sideEffects: true,
},
// Adds support for CSS Modules (https://github.com/css-modules/css-modules)
// using the extension .module.css
{
test: cssModuleRegex,
// etc
I created a new React app with create-react-app (using React ver. 16.6.3). Now I want to use SCSS for my components. So first I ran the eject script. Then in webpack.config.dev.js I did the following edit:
{
test: cssRegex,
exclude: cssModuleRegex,
use: getStyleLoaders({
importLoaders: 1,
modules: true,
localIdentName: '[name]__[local]__[hash:base64:5]'
}),
}
I also installed node-sass package.
Then I created my Test .scss file:
.Test {
background-color: gold;
.Header {
color: lighten(purple, 20%);
}
}
And my Test component with importing the .scss file
import React from 'react';
import style from './test.scss';
const Test = (props) => (
<div className={style.Test}>
This is div1
<div className={style.Header}>Div 2</div>
</div>
);
export default Test;
That didn't work and I didn't see any styling. I tried to import the .scss directly and use it:
import './test.scss';
...
<div className='Test'>
This is div1
<div className={style.Header}>Div 2</div>
</div>
...
That did work and I saw the styling on the div with className='Test'.
I tried to change the webpack as follows:
const CSSModuleLoader = {
loader: 'css-loader',
options: {
modules: true,
sourceMap: true,
localIdentName: '[local]__[hash:base64:5]',
minimize: true
}
}
const CSSLoader = {
loader: 'css-loader',
options: {
modules: false,
sourceMap: true,
minimize: true
}
}
const postCSSLoader = {
loader: 'postcss-loader',
options: {
ident: 'postcss',
sourceMap: true,
plugins: () => [
autoprefixer({
browsers: ['>1%', 'last 4 versions', 'Firefox ESR', 'not ie < 9']
})
]
}
}
...
{
test: /\.scss$/,
exclude: /\.module\.scss$/,
use: ['style-loader', CSSLoader, postCSSLoader, 'sass-loader']
},
{
test: /\.module\.scss$/,
use: [
'style-loader',
CSSModuleLoader,
postCSSLoader,
'sass-loader',
]
},
At first I got an autoprefixer not defined error. I imported it with const autoprefixer = require('style-loader') - that made this error disappear, though I'm still not convinced that was the correct require and correct fix.
But then I got the following error:
Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.
- configuration.module.rules[2].oneOf[0].use should be one of these:
non-empty string | function | object { loader?, options?, ident?, query? } | function | [non-empty string | function | object { loader?, options?, ident?, query? }]
-> Modifiers applied to the module when rule is matched
Details:
* configuration.module.rules[2].oneOf[0].use should be a string.
* configuration.module.rules[2].oneOf[0].use should be an instance of function
* configuration.module.rules[2].oneOf[0].use should be an object.
* configuration.module.rules[2].oneOf[0].use should be an instance of function
* configuration.module.rules[2].oneOf[0].use[1] should be a string.
* configuration.module.rules[2].oneOf[0].use[1] should be an instance of function
* configuration.module.rules[2].oneOf[0].use[1] has an unknown property 'loaders'. These properties are valid:
object { loader?, options?, ident?, query? }
Don't know how to deal with that...
How do I configure webpack to either immediately compile .scss to .css in the same directory (that way I can import .css and use it regularly with style.Class) or to use the .scss import in my file in the same manner and later compile it to .css for production?
Please use below rules in webpack file and remove extra code.
rules: [
{
test: /\.s?css$/,
use: [
'style-loader',
'css-loader',
'sass-loader'
]
}
]
I have been using webpack 4.6.0:
I have following issue when compiling:
Uncaught Error: Module parse failed: Unexpected token (1:4)
You may need an appropriate loader to handle this file type.
| div {
| background-color: yellow;
| color: red;
my webpck config is as following:
var path = require('path');
var webpack = require('webpack');
module.exports = {
mode:'development',
entry: './src/code/app.js',
output: { path: __dirname, filename: 'bundle.js'},
watch: true,
module: {
rules: [
{
test: /.jsx?$/,
loader: 'babel-loader',
exclude: /node_modules/,
query: {
plugins: "transform-class-properties",
presets: ['es2015', 'react']
}
},
{
// Do not transform vendor's CSS with CSS-modules
// The point is that they remain in global scope.
// Since we require these CSS files in our JS or CSS files,
// they will be a part of our compilation either way.
// So, no need for ExtractTextPlugin here.
test: /\.css$/,
include: /node_modules/,
loader: 'css-loader'
}
]
}
};
and I have :
"css-loader": "^0.28.11",
and my file struct is like:
root:
-src
|-code
|-XXXX.js
|-css
|-HomePage.css
I think it is something related to my css loader, I have tried many methods online, but none of them works. Is there something related to my file structure?
I believe you still need to add a rule for your own css files. Try adding this to your rules.
{
// Preprocess your css files
// you can add additional loaders here (e.g. sass/less etc.)
test: /\.css$/,
exclude: /node_modules/,
use: ['style-loader', 'css-loader'],
}
In my Vue component, I changed the language from the default CSS to the explicitly set SCSS, like this.
<style lang="scss">
div.bordy{ border: solid 3px red; }
</style>
I also changed the webpack.config.js according to this post by LinusBorg, so it looks like this.
module.exports = {
entry: ["babel-polyfill", "./index.js"],
output: { path: __dirname, filename: "bundle.js" },
module: {
loaders: [
{ test: /\.js$/, loader: "babel", exclude: /node_modules/ },
{ test: /\.vue$/, loader: "vue" },
// { test: /\.scss$/, loader: 'style!css!sass' },
{ test: /\.s[a|c]ss$/, loader: "style!css!sass" }
]
},
babel: {
presets: ["es2015", "stage-3"],
plugins: ["transform-runtime"]
},
vue: { loaders: [{ scss: "style!css!sass" }] },
resolve: { alias: { "vue$": "vue/dist/vue.common.js" } }
}
The guy explains that by doing so, we catch SCSS and map it to SASS. However, I'm getting an error saying the following.
Module not found: Error: Cannot resolve module 'scss-loader'
I've tried installing the packages as shown below but it gave no difference in the output error.
npm install scss-loader --save-dev
Here, I get uncertain and googlearching leads me to more confusion because I'm reading hints in all possible directions, not rarely commented with angry shouts of not resolving the issue.
Should I use style lang="sass" to being with?
When I try that, I have to install node-sass and I'm not sure if I'm resolving the problem or hiding it...
You have to install sass-loader and node-sass and it's resolving the problem not hiding it.
sass-loader documentation clearly says:
The sass-loader requires node-sass and webpack as peerDependency. Thus you are able to specify the required versions accurately.
and here are peerdependency from it's package.json:
"peerDependencies": {
"node-sass": "^3.4.2 || ^4.0.0",
.....
Which means sass-loader will work with these versions of node-sass.
It requires it in the very 4th line of it's code - sass-loader/index.js:
'use strict';
var utils = require('loader-utils');
var sass = require('node-sass');
Once you have it installed, you can do any of following:
<style lang="scss">
or
<style lang="sass">
as you are going to use same loader for both of these.