In the bitbucket server client side extension plugin template I have used a react module component for checkbox tree view and configured in the webpack config a css loader.
However, while importing the css file within the js code, shows no error, the classes imported are not effective in the component.
Am I missing a step or does bitbucket somehow override these classes by the one provided by the server itself?
Can you share more about your CSS styling approach? Are you using webpack css-loader
with or without CSS modules? Does the problem exist in webpack dev-server or after you bundle webpack in production mode?
I can suggest doing that:
- try using some distinguished names for one of the CSS classes you use with React components
- build/bundle the plugin in production mode. Run the plugin in Bitbucket.
- Use Chrome Devtools and run a global search to find your class name.
You can turn on a global search in devtools using a keyboard shortcut:
Mac: Command+Option+F
Windows/Linux Control+Shift+F
Opens the Search tab in the Drawer , which lets you search for text across all loaded resources
Let me know what are your findings
@madamczak Thanks for the prompt reply as usual.
I have tried packaging (via atlas-package) the plugin and uploaded it on my bitbucket server instance, using the Devtools on chrome as suggested I was able to search and find reference to my css classes in “extensions-pull-request-diff-toolbar-extension-js.chunk.js”, however, they are somehow not applied. I have the impression that aui are somehow overriding these.
My CSS styling approach is the following, I have a css-loader configured for webpack.
A snippet of my “webpack.loaders.js”
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const { I18N_FILES } = require('./webpack.constants');
function getLoaders({ isProductionEnv = false }) {
return [
{
test: /\.css$/,
use: [
{
loader: 'css-loader',
options: {
import: true,
},
},
],
},
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: [
{
loader: '@atlassian/i18n-properties-loader',
options: {
i18nFiles: I18N_FILES,
disabled: isProductionEnv,
},
},
{
loader: 'babel-loader',
options: {
cacheDirectory: true,
},
},
],
},
{
test: /\.less$/,
use: [
{
loader: isProductionEnv ? MiniCssExtractPlugin.loader : 'style-loader',
options: {
sourceMap: true,
},
},
{
loader: 'css-loader',
options: {
sourceMap: true,
},
},
{
loader: 'less-loader',
options: {
sourceMap: true,
},
},
],
},
{
test: /\.(png|jpg|gif|svg)$/,
use: [
{
loader: 'file-loader',
options: {},
},
],
},
{
test: /\.soy$/,
use: [
{
loader: '@atlassian/i18n-properties-loader',
options: {
I18N_FILES,
disabled: isProductionEnv,
},
},
{
loader: '@atlassian/soy-loader',
options: {
dontExpose: true,
},
},
],
},
{
test: /\.cse.graphql$/,
loader: '@atlassian/clientside-extensions-schema/loader',
},
];
}
module.exports.loaders = isProduction => getLoaders(isProduction);
Then I simply import the css in my plugin js file like this:
import "./styles.css"
Example css file:
@import url("https://fonts.googleapis.com/css?family=Lato");
body {
background-color: #eee;
}
#app {
border-radius: 3px;
border: 1px solid #e5e5e5;
margin: 15px;
background-color: white;
}
.tab {
width: 100%;
padding: 25px;
font-family: sans-serif;
color: #444;
}
ul.inline {
list-style: none;
padding: 0;
margin-bottom: 0;
-webkit-margin-before: 0;
-webkit-margin-after: 0;
-webkit-margin-start: 0px;
-webkit-margin-end: 0px;
-webkit-padding-start: 0px;
}
ul.inline,
li {
display: inline-block;
margin-left: 0;
padding: 10px;
border-bottom: 2px solid #eee;
transition: all 0.5s;
font-family: Lato, sans-serif;
font-weight: 300;
cursor: pointer;
color: #aaa;
}
ul.inline,
li.selected {
border-bottom: 2px solid #337ab7;
color: #444;
}
I noticed that if I have the css classes inlined in js and apply the style in the component via style attribute it works. Example below:
dummyComponent.js:
import React, { Component } from "react";
const style = {
"tab": {
"width": "100%",
"padding": "25px",
"fontFamily": "sans-serif",
"color": "#444"
}
};
class Tabs extends Component {
state = {
selected: this.props.selected || 2
};
render() {
return (
<div style={style.tab}>{this.props.children[this.state.selected]}</div>
);
}
}
export default Tabs;
But, somehow classNames when importing the css do not.
I could of course work around this and change every classname to style attribute and reference the inline css, but, this is very impractical especially that I am using some OSS components which come with default css style sheets, and in that case I’ll have to dig in the module and change every className to a style attribute, but, this can get overwhelming with big components.
This is also problematic with element styles like “ul.inline”.
I think the problem is that your css-loader
is missing the additional required MiniCssExtractPlugin
and style-loader
configuration that will handle injecting the CSS files. Similar to what we are doing with .less
files:
{
test: /\.css$/,
use: [
{ // Add this lines before css-loader
loader: isProductionEnv ? MiniCssExtractPlugin.loader : 'style-loader'
},
{
loader: 'css-loader',
options: {
import: true,
},
},
]
},
BTW: If you are using webpack v4 you should keep using the css-loader
v2. The v3 version of the css-loader
is compatible with webpack 5+ only:
I also updated the template proejct to include the mentioned css-loader
changes:
Let me know if that helps.
Thanks,
Maciej Adamczak
Atlassian Developer
Indeed the MiniCssExtractPlugin
and style-loader
configuration solved it.
It is very nice to have this added to the template master. Thanks!