Using relative paths in SASS background images - css

I'm trying to get background images to work in my Angular project's SASS when I don't know where the application root will be. For example, the app's home page could be:
localhost:9000/home
or
localhost:9000/foo/home
or
localhost:9000/bar/home
I figured I could address this by just making the paths in my background-image properties relative, like this:
div {
background-image: url("assets/smiley.png");
}
However, that doesn't work. When I compile the app, it can't find the assets. In the console, it says:
Error: Can't resolve './assets/smiley.png'
It gives me this same message whether my background-image url value starts with ./ or not. But even ./ I imagine should work.
What DOES work is if I hard-code the path into the background-image property, making the path ABSOLUTE, like so:
div {
background-image: url("/foo/assets/smiley.png");
}
However, that's not an option, since I don't know if the app root will be at /foo/ or /bar/ or something else.
Another thing that works is using the --base-href option of ng build to hard-code the path, like so:
ng build --base-href /foo/
But if possible, I'd really like to accomplish this with code changes that don't involve passing parameters to the ng build command on a build-by-build basis.
Here is my Webpack Config located at node_modules/#angular/cli/models/webpack-config.js. Is that the right file? Sorry if it's not - I'm pretty unfamiliar with webpack:
/**
* Adapted from angular2-webpack-starter
*/
const helpers = require('./config/helpers'),
webpack = require('webpack');
/**
* Webpack Plugins
*/
const ProvidePlugin = require('webpack/lib/ProvidePlugin');
const DefinePlugin = require('webpack/lib/DefinePlugin');
const LoaderOptionsPlugin = require('webpack/lib/LoaderOptionsPlugin');
module.exports = {
devtool: 'inline-source-map',
resolve: {
extensions: ['.ts', '.js']
},
entry: helpers.root('ng2-translate.ts'),
output: {
path: helpers.root('bundles'),
publicPath: '/',
filename: 'ng2-translate.umd.js',
libraryTarget: 'umd',
library: 'ng2-translate'
},
// require those dependencies but don't bundle them
externals: [/^\#angular\//, /^rxjs\//],
module: {
rules: [{
enforce: 'pre',
test: /\.ts$/,
loader: 'tslint-loader',
exclude: [helpers.root('node_modules')]
}, {
test: /\.ts$/,
loader: 'awesome-typescript-loader?declaration=false',
exclude: [/\.e2e\.ts$/]
}]
},
plugins: [
// fix the warning in ./~/#angular/core/src/linker/system_js_ng_module_factory_loader.js
new webpack.ContextReplacementPlugin(
/angular(\\|\/)core(\\|\/)(esm(\\|\/)src|src)(\\|\/)linker/,
helpers.root('./src')
),
new webpack.LoaderOptionsPlugin({
options: {
tslintLoader: {
emitErrors: false,
failOnHint: false
}
}
})
]
};

Related

How to generate javascript file, which can be loaded via script tag by a non nextjs web page

In my current project we are migrating an application to nextjs. Now I would like to inject a react component into a legacy page through including a script, which is using code from the new nextjs application. Her a simplified version of the script:
function injectCode() {
const container = document.getElementById("container")
const reactRoot = createRoot(container)
reactRoot.render(<ExistingComponent />)
}
document.addEventListener('load', injectCode)
How can I generate a js file, that can be included into a webpage not rendered by nextjs? Best would be to generate the file with next build, but directly running webpack would be ok as well.
Until now I tried to write my own webpack config and just run webpack directly. It would be ok if I run webpack once and check the generated file into git. Therefore the generated file is put into the public folder.
This is not the only webpack config I tried, but after too many iterations solving one problem and getting the next I gave up thinking there is probably an easier solution.
module.exports = {
entry: './script.tsx',
module: {
rules: [
{
test: /\.(ts|tsx)?$/,
use: 'ts-loader',
exclude: /node_modules/,
},
{
test: /\.(ts|tsx)?$/,
include: path.resolve(__dirname, 'lib'),
use: [
{
loader: 'ts-loader',
},
],
},
{
test: /\.(ts|tsx)?$/,
include: path.resolve(__dirname, 'components'),
use: [
{
loader: 'ts-loader',
},
],
},
{
test: /\.(ts|tsx)?$/,
include: path.resolve(__dirname, 'single-header-footer'),
use: [
{
loader: 'ts-loader',
},
],
},
{
test: /\.(js)?$/,
include: path.resolve(__dirname, 'node-modules'),
use: [
{
loader: 'ts-loader',
},
],
},
],
},
resolve: {
extensions: ['.tsx', '.ts', '.js'],
},
output: {
path: path.resolve(__dirname, 'public'),
filename: 'next-js-component.js',
},
}
I am probably missing a lot of settings which are required.
The second thing I tried was extending the webpack configuration within the next.config.js file:
...
webpack: (config, { buildId, dev, isServer, defaultLoaders, nextRuntime, webpack }) => {
const originalEntry = config.entry
config.entry = async () => {
const entries = await originalEntry()
entries['next-js-component'] = ['script.tsx']
return entries
}
return config
},
...
This creates a chunk file .next/static/chunks/next-js-component-dc0ae8d2d7a87ec9.js. But I don't know how to use this file. Probably I need to add some other code into the page which loads the created chunk and additional chunks.
The header and footer of the legacy pages are already rendered by the next.js app and are included into the page via server side include. So I might be able to use something like the HtmlWebpackPlugin to inject the correct script tag into the header, which is then included into the legacy page.

Multiple Tailwind CSS classes having multiple Webpack entry points

Problem statement
So I have a React project setup with webpack and tailwind CSS.
In my webpack config I have multiple entry point in order to generate different CSS and JS for each entry point.
The problem arises when I use the tailwind classes in my React components.
Let's suppose if I use a tailwind class bg-red-600 only in Component1(or entry point 1).
So after building the files through webpack the bg-red-600 will be present in all the entry point's generated CSS files(keep in mind I have just used this class in first entry point component only).
What it should be doing is only have bg-red-600 class in first component CSS file instead it is preset in all the CSS files even though I have not used it in any other place other than first component.
Hope I was able to made my point.
Thanks.
Webpack's entry points:
entry: {
app1: path.resolve(
__dirname,
'src/Component1'
),
app2: path.resolve(
__dirname,
'src/Component2'
),
},
Here is my solution:
/config folder with custom tailwind-xxx.config file for each entry js
eg. /config/tailwind-ConfirmButton.config.js:
module.exports = {
content: [
'./src/common/ConfirmButton/ConfirmButton.jsx',
],
// plugins: [require('#tailwindcss/forms')],
}
webpack.config.js
const postcssOpts = { postcssOptions: env => {
// here is the point
const component = env._module.context.slice(env._module.context.lastIndexOf('/') + 1)
return {
plugins: [
['tailwindcss', {
config: `./config/tailwind-${component}.config.js`,
}],
autoprefixer
]
}
}
}
...
entry: {
confirm: path.resolve(__dirname, './src/widgets/confirmButton.js'),
},
target: ['web', 'es5'], // <=== can be omitted as default is 'web'
output: {
filename: '[name]/tag.js',
path: path.resolve(__dirname, 'dist/exp'),
publicPath: './',
},
...
{
test: /\.css$/,
use: [
{ loader: 'style-loader' },
{ loader: 'css-loader' },
{
loader: 'postcss-loader',
options: postcssOpts,
},
],
},
entry widget js
eg. /src/widgets/customButton.js:
...
render(
<ConfirmButton
expId={expId}
content={content}
confirmBtn={confirmBtn}
cancelBtn={cancelBtn}
field={field}
/>,
container
)
finally run weppack --mode=production

Unable to load CSS correctly for external library in Storybook Angular

I am using Angular with Projects style setup (with --create-application=false) and I just cannot get Storybook to load any CSS from external libraries like Angular Material. The project component scss compiles and works fine but none of the external libraries can load any css.
Here is my storybook/main.js -
const path = require('path');
module.exports = {
"stories": [
"../stories/**/*.stories.mdx",
"../stories/**/*.stories.#(js|jsx|ts|tsx)"
],
"addons": [
"#storybook/addon-links",
"#storybook/addon-essentials"
],
webpackFinal: async (config, { configType }) => {
// `configType` has a value of 'DEVELOPMENT' or 'PRODUCTION'
// You can change the configuration based on that.
// 'PRODUCTION' is used when building the static version of storybook.
// Make whatever fine-grained changes you need
config.module.rules.push({
test: /\.scss$/,
use: ['style-loader', 'css-loader', 'sass-loader'],
include: path.resolve(__dirname, '../'),
});
// Return the altered config
return config;
}
}
Here is my project structure -
Can someone please point out what the problem is?

Using LESS CSS with the latest Create React App

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

How to integrate WordPress into Webpack?

I developed a website front-end using HTML/CSS, JavaScript and Sass or Scss. I used NPM.
I need to put that website into WordPress. I already installed WordPress and put that folder with all my assets(HTML/CSS, JS, Sass etc..) into theme folder.
Now, what do I do now? How do I connect all of this?
I know it's possible because I have worked on a site like this before at work, but not sure how to do it from the ground up.
Webpack -> WordPress. I will watch the files with NPM or webpack, but the hosting will be doing with MAMP - that's how I did it at work anyways.
What should I do?
This is the website code if anything: https://github.com/AurelianSpodarec/lovetocodefinal
PS, no WordPress API or any stuff like that, but just as I wrote above.
I found a solution to this.
It's simple. You need to compile everything and put it in the folders that will be used by WordPress and do WordPress magic to get the styles with functions.
I have made this here: https://github.com/AurelianSpodarec/Webpack-to-WordPress-Starting-Template
It's not perfect, but a good starting point for those who are looking on using Webpack with WordPress.
Old Question, but just had the same one myself. I just built a light Wordpress-Webpack starter. You can use it to build Wordpress-Themes and it will build Scss and copy PHP etc. into the destination of your Themes. It uses Browsersync for easier development. You have complete separation of dev and build :) Maybe this can still help in future. Regards, Fabian
Link: https://github.com/fabiankuhn/webpack-wordpress
Extract from Main Build config (Paths):
const themeName = 'test-theme'
const themePath = '/Users/<Username>/<repos>/Test/webpack/wordpress/wp-content/themes'
/*
* Main Config
*/
module.exports = {
entry: './webpack-entry.js', // Main Entry: Is included in functions.php
output: {
filename: 'main.js', // Is included in functions.php
// Set Path of Wordpress Themes ('.../wp-content/themes') as absolute Path
path: themePath + '/' + themeName + '/assets',
},
Extract from Wordpress webpack config:
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CopyPlugin = require('copy-webpack-plugin');
const BrowserSyncPlugin = require('browser-sync-webpack-plugin')
// This Config Exports the FIles with Source Maps for Wordpress Development
module.exports = merge(common, {
mode: 'development',
devtool: 'inline-source-map', // Use Source-Maps for Debug
plugins: [
// Plugin to Reload Browser According to Proxy 127.0.0.1:8080 (Wordpress PHP)
new BrowserSyncPlugin({
host: 'localhost',
port: 3000,
proxy: '127.0.0.1:8080',
files: [
{
match: [
'**/*.php',
'**/*.js',
'**/*.css',
],
},
],
notify: false,
},
{
reload: true,
}),
// Extract CSS
new MiniCssExtractPlugin({
filename: '[name].css',
chunkFilename: '[id].css',
}),
// Copy all Files to Entry Output Path except Github, Webpack and
// Original Sources (Before Webpack Processing)
new CopyPlugin([
{
from: '../',
to: '../',
ignore: [
'_webpack/**',
'assets/**',
'.git/**',
],
},
]),
],
module: {
rules: [
{
// Listen for Sass and CSS
test: /\.(sa|sc|c)ss$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
},
},
// Source Map shows Path in Chrome for Testing
{ loader: 'css-loader', options: { sourceMap: true, importLoaders: 1 } },
{ loader: 'sass-loader', options: { sourceMap: true } },
],
},
],
},
});

Resources