How to integrate WordPress into Webpack? - wordpress

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 } },
],
},
],
},
});

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.

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?

Firebase hosting showing generic message

I was building a WhatsApp clone app (https://github.com/adrielwerlich/curso-hcode-whatsapp-clone)
running the build command
run the firebase deploy --only hosting command
But this screen is what I´m getting
And the Firebase dashboard is displaying
Update
I was able to make some advances.
I added to
webpack.config.js
new HtmlWebpackPlugin({
template: './index.html',
})
and now there is proper html content...
but the app.bundle.js is giving a error message when I try to use firebase serve
After discovering that the bundle was only creating the js files, and was necessary to also configure the HtmlWebpackPlugin to create the HTML file the problem was to make the js files visible to the html files.
So the final solution to make the bundle run inside local firebase serve command and remote firebase hosting service...
The whole issue was about the webpack bundle config
webpack.config.js
const path = require('path')
var HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry:{
app:'./src/app.js',
'pdf.worker':'pdfjs-dist/build/pdf.worker.entry.js'
},
output:{
filename:'[name].bundle.js',
path: path.join(__dirname, '/dist'),
publicPath:'/' // the issue was here. Instead of /dist only / makes the js bundle files visible inside the html index file
},
module: {
loaders: [
{
test: /\.css/,
loaders: ['style-loader', 'css-loader']
// include: __dirname + '/'
},
{
test: /.(gif|png|jpe?g|webp|svg)$/i,
use: [
'file-loader',
{
loader: 'image-webpack-loader',
options: {
webp: {
quality: 80
}
}
}
]
}
],
},
plugins: [
new HtmlWebpackPlugin({
template: './index.html',
})
]
}
and also had to configure de css-style loader and the image webpack loader in order to run properly inside firebase localhost server and firebase remote hosting service
Suffering with the small details of bundle builder configuration... many hours of anxiety...

Using relative paths in SASS background images

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
}
}
})
]
};

How does one deploy a ReactJs component that imports its own stylesheets?

I'm developing a large React component that I want to import into another React app. (I could have done it all as one big app, but I decided to separate this component into a its own project so that I could focus on the component separately.) It uses its own stylesheets, which it pulls in with "require('path/to/stylesheet.[s]css')".
For development, I serve it with webpack-dev-server which takes care of loading and pre-processing those stylesheets. My problem is that I don't know how to deploy the component so that another app can include it without breaking when the browser encounters those calls to require(path/to/stylesheet).
I've found lots of examples where projects use webpack-dev-server for development, but invoke babel (or other pre-processors) directly in order to deploy components to a dist/ directory, so this seems to be a common practice. But what to do about those invocations of "require('path/to/stylesheet.[s]css')"? Without webpack and its loaders to rely on, they all fail.
Ideally, I'd like to be able to use webpack for both development and production. Then I could deploy my component as a complete bundle and the css would be included in the code. I tried this earlier but it didn't work. It also has the disadvantage of making it hard for the main app to over-ride the styles in the component.
I suppose another way might be to set up my pipeline so that a main.scss includes all the other stylesheets and let Sass output a single style.css file that the consuming app has to include separately. Less elegant, but it makes it easier to override these styles.
I'm still mastering React and its eco-system, so I'd love to know what the best practice is for this in case anyone knows.
You need to run webpack and bundle all of your JS/CSS so that it can be consumed in your other project. If you use the correct loaders, the CSS is bundled directly into your JS bundle. Or, you can use a different loader to have webpack generate you a nice style.css file that bundles all your require(/path/to/css) into one file.
There are three or four basic things you need to do (Assuming webpack#3.*):
Use the "externals" in your webpack config file to exclude libraries in your package.json dependencies list.
Use babel-loader to transpile your javascript (ES2015 is supported by most browsers).
Use 'style-loader', 'css-loader', and 'sass-loader' to bundle your css/scss into your webpack js bundle. (This assumes you aren't using server-side react rendering. That's a bit trickier. You would need to use an isomorphic style loader instead.)
Optionally, use the extract-text-webpack-plugin to pull your css out into a separate file. (Commented out in the example below)
Be sure to make your bundle.js file the entry point in your package.json
Here is a good example of what you are trying to do: (This example works for server-side rendering as well as browser rendering. The BABEL_ENV lets us only require css files on the browser.)
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const env = process.env.NODE_ENV;
console.log('Environment: ', env)
module.exports = {
devtool: 'source-map',
entry: env == 'production' ? './src/components/index.js' : './src/index.js',
output: {
path: env !== 'production' ? require('path').resolve('./dev'): require('path').resolve('./dist'),
filename: 'bundle.js',
publicPath: '/',
library: 'reactPorto',
libraryTarget: 'umd'
},
externals: env == 'production' ? [
'jquery',
'react',
'react-dom',
'react-bootstrap',
/^react-bootstrap\/.+$/,
'classnames',
'dom-helpers',
'react-owl-carousel',
'react-owl-carousel2',
'uncontrollable',
'warning',
'keycode',
'font-awesome'
] : [],
devServer: {
inline: true,
contentBase: './dev',
staticOptions: { index: 'test.html' },
historyApiFallback: {
rewrites:[{ from: /./, to: 'test.html' }],
},
hot: true,
},
plugins: [
// new ExtractTextPlugin({
// filename: 'style.css',
// allChunks: true
// }),
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': JSON.stringify(env || 'development'),
'BABEL_ENV': JSON.stringify(env || 'development')
}
}),
new webpack.optimize.OccurrenceOrderPlugin(),
...(env != 'production' ? [new webpack.HotModuleReplacementPlugin()] : []),
...(env == 'production' ? [new webpack.optimize.UglifyJsPlugin({ sourceMap: true, compress: { warnings: false } })] : []),
new webpack.NoEmitOnErrorsPlugin()
],
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
query: {
presets: [
'es2015',
'react',
'stage-2',
...(env != 'production' ? ['react-hmre'] : [])
],
plugins: []
}
}
},
{
test : /(\.css|\.scss)/,
// exclude: /node_modules/,
// use : ExtractTextPlugin.extract({
// use: [
// 'isomorphic-style-loader',
// {
// loader: 'css-loader',
// options: {
// importLoaders: 1
// }
// },
// 'sass-loader'
// ]
// }),
use: ['iso-morphic-style-loader', 'css-loader', 'sass-loader']
},
{test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: 'file-loader?mimetype=image/svg+xml'},
{test: /\.woff(\?v=\d+\.\d+\.\d+)?$/, loader: "file-loader?mimetype=application/font-woff"},
{test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/, loader: "file-loader?mimetype=application/font-woff"},
{test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: "file-loader?mimetype=application/octet-stream"},
{test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: "file-loader"},
{test: /\.(png|jpg|jpeg)/, loader: 'file-loader' }
]
}
}

Resources