I'm in the middle of upgrading an app from rails 3.2 to rails 4.2 using webpacker gem everything works fine in localhost I have compiled my assets and run
RAILS_ENV=production rails s
but I have errors when pushing to heroku it compiles all assets even the packs but generates errors in js, I use angular in many parts of the app and the error is related with dependency injection
check link
The main problem here was the unglifier gem I had to coment the uglifier
#config.assets.js_compressor = :uglifier
The next part was the configuration for webpack in production that look like this:
const webpack = require('webpack')
const { basename, dirname, join, relative, resolve } = require('path')
const merge = require('webpack-merge')
const CompressionPlugin = require('compression-webpack-plugin')
const sharedConfig = require('./shared.js')
const { env, settings, output, loadersDir } = require('./configuration.js')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const ManifestPlugin = require('webpack-manifest-plugin')
module.exports = merge(sharedConfig, {
output: { filename: '[name]-[chunkhash].js' },
devtool: false,//'source-map',
stats: 'normal',
plugins: [
new webpack.EnvironmentPlugin(JSON.parse(JSON.stringify(env))),
new ExtractTextPlugin({
filename: '[name]-[hash].css',
allChunks: true
}),
new ManifestPlugin({
publicPath: output.publicPath,
writeToFileEmit: true
})
],
resolve: {
extensions: settings.extensions,
modules: [
resolve(settings.source_path),
'node_modules'
],
alias: {
'vue$': 'vue/dist/vue.esm.js' // 'vue/dist/vue.common.js' for webpack 1
}
},
resolveLoader: {
modules: ['node_modules']
}
})
Now I can deploy and the assets are working.
Related
im trying to build my express app with webpack and i got a lot of errors i tried a lot of configs but nothing works , im using nodejs with express and ejs templating this is my first time using it to create something , i need to build it so i can deploy it , but i couldnt with all these errors:
const express = require("express");
var minify = require("express-minify");
const MainRoute = require("./routes/index");
const driver = require("./routes/driver");
const session = require("express-session");
const MySQLStore = require("express-mysql-session")(session);
const mysql = require("mysql2");
const crypto = require("crypto");
const bcrypt = require("bcrypt");
const multer = require("multer");
const path = require("path");
const Chart = require('chart.js/auto');
const Canvas = require('canvas');
const ejs = require('ejs');
const fs = require('fs');
// define the include function
ejs.filters.include = function(file, data) {
const filePath = path.join(__dirname, file);
const fileContent = fs.readFileSync(filePath, 'utf8');
return ejs.render(fileContent, data);
};
const app = express();
app.use(
minify({
cache: false,
uglifyJsModule: null,
errorHandler: null,
jsMatch: /javascript/,
cssMatch: /css/,
jsonMatch: /json/,
sassMatch: /scss/,
lessMatch: /less/,
stylusMatch: /stylus/,
coffeeScriptMatch: /coffeescript/,
})
);
app.use("/uploads", express.static(path.join(__dirname, "uploads")));
//------ Routes -------//
app.set("view engine", "ejs");
app.use(express.static("public"));
app.use("/", MainRoute);
app.use("/", driver);
// rest of the code
//---------- Server is on ---------//
app.listen(1000, () => {
console.log("Server is On!!");
});
and my webpack.config.js :
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
mode: 'production',
resolve: {
fallback: {
path: require.resolve("path-browserify"),
fs: false,
tls:false,
net:"empty",
"less": require.resolve("less"),
"vm": require.resolve("vm-browserify"),
"vm": false ,
https: require.resolve('https-browserify'),
crypto: require.resolve("crypto-browserify"),
stream: require.resolve("stream-browserify"),
zlib: require.resolve("browserify-zlib"),
assert: require.resolve("assert/"),
buffer: require.resolve("buffer/"),
process: require.resolve("process/browser"),
url: require.resolve("url/"),
os: require.resolve("os-browserify/browser"),
"timers": require.resolve("timers-browserify"),
"http": require.resolve("stream-http"),
"constants": require.resolve("constants-browserify"),
},
},
entry: {
server: './server.js'
},
output: {
path: path.resolve(__dirname, 'public'),
filename: '[name].js'
},
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules)/,
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env', '#babel/preset-stage-2']
}
}
},
{
test: /\.ejs$/,
loader: 'ejs-loader',
options: {
esModule: false
}
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './views/index.ejs',
hash: true,
})
],
node: {
__dirname: false
},
target: 'node'
};
im new to nodejs i hope you guys would help me!
i tried to change the webpack configs and install all the dependencies
ERROR in ./server.js
Module build failed (from ./node_modules/babel-loader/lib/index.js):
Error: [BABEL] C:\Users\anasa\Desktop\ADROAD\server.js:
As of v7.0.0-beta.55, we've removed Babel's Stage presets.
Please consider reading our blog post on this decision at
https://babeljs.io/blog/2018/07/27/removing-babels-stage-presets
for more details. TL;DR is that it's more beneficial in the
long run to explicitly add which proposals to use.
For a more automatic migration, we have updated babel-upgrade,
https://github.com/babel/babel-upgrade to do this for you with
"npx babel-upgrade".
If you want the same configuration as before:
{
"plugins": [
// Stage 2
["#babel/plugin-proposal-decorators", { "legacy": true }],
"#babel/plugin-proposal-function-sent",
"#babel/plugin-proposal-export-namespace-from",
"#babel/plugin-proposal-numeric-separator",
"#babel/plugin-proposal-throw-expressions",
// Stage 3
"#babel/plugin-syntax-dynamic-import",
"#babel/plugin-syntax-import-meta",
["#babel/plugin-proposal-class-properties", { "loose": false }],
"#babel/plugin-proposal-json-strings"
]
}
If you're using the same configuration across many separate projects,
keep in mind that you can also create your own custom presets with
whichever plugins and presets you're looking to use.
module.exports = function() {
return {
plugins: [
require("#babel/plugin-syntax-dynamic-import"),
[require("#babel/plugin-proposal-decorators"), { "legacy": true }],
[require("#babel/plugin-proposal-class-properties"), { "loose": false }],
],
presets: [
// ...
],
};
};
(While processing: "C:\\Users\\anasa\\Desktop\\ADROAD\\node_modules\\#babel\\preset-stage-2\\lib\\index.js")
ERROR in Template execution failed: ReferenceError: _ is not defined
ERROR in ReferenceError: _ is not defined
- index.ejs:10 module.exports
C:/Users/anasa/Desktop/ADROAD/views/index.ejs:10:26
- index.js:450
[ADROAD]/[html-webpack-plugin]/index.js:450:16
- task_queues:95 process.processTicksAndRejections
node:internal/process/task_queues:95:5
- async Promise.all
webpack 5.75.0 compiled with 3 errors in 1650 ms
Probably you're using a deprecated stage preset.
Try to fix it with this:
1 - Install the right preset:
npm install --save-dev #babel/preset-env
2 - If you have a babel config file like .babelrc or babel.config.js make it use this preset instead, or update your webpack plugin instead:
{
"presets": [
["#babel/preset-env", {
"targets": {
"node": "current"
}
}]
]
}
3 - Remove the stage-0 and stage-1 presets from your Babel configuration.
Hope that help!
I am currently using manual reloads with npx webpack which are time consuming.
So, attempting to implement HMR using Webpack docs and this tutorial
It does not throw any errors when I run npm start, tells me that files were generated but the files are not available in the destination directory /dist. If they are placed somewhere else, I could not find.
Also, the HMR as such seems to be working in the sense that it automatically recompiles once changes are made to the app files.
It automatically opens localhost:8080 as well, but shows only the directory list or a message like CANNOT GET.
By the way, I do not use Symfony Encore.
The directory looks like this:
- bin
- client // where the React files are
- config // Symfony
- node_modules
- public
- dist // here goes Webpack's output ( normally )
- index.php
- src // Symfony app files
- templates - Twig
- var
- vendor
webpack.config.js
The above webpack.config.js looks like below, in the latest config attempt
const webpack = require('webpack');
const { InjectManifest } = require('workbox-webpack-plugin');
const ManifestPlugin = require('webpack-manifest-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractCssChunks = require('extract-css-chunks-webpack-plugin');
const HardSourceWebpackPlugin = require('hard-source-webpack-plugin');
const path = require('path');
const useDevServer = true;
const publicPath = useDevServer ? 'http://localhost:8080/public/dist/' : '/dist/';
console.log('path', path.resolve(__dirname, 'public/dist'));
console.log('public path', publicPath);
module.exports = {
mode: 'development',
entry: './client/index.js',
output: {
path: path.resolve(__dirname, 'public/dist'),
filename: '[name].[hash].js',
publicPath,
},
devtool: 'inline-source-map',
module: {
....
},
devServer: {
// contentBase: './dist',
hot: true,
allowedHosts: [
'http://127.0.0.1:8000',
'http://127.0.0.1:8001',
'http://localhost:8000',
'http://localhost:8001',
],
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
...
So I am working on a simple card game, where i have like 40 images relate to the cards. I am using Vue Cli that already comes with a simple webpack configuration.
So basicly I am saving all the images on the static folder like this:
When I build the project for production, generating the dist folder, it creates the images like this:
this is my webpack production file:
'use strict'
const path = require('path')
const utils = require('./utils')
const webpack = require('webpack')
const config = require('../config')
const merge = require('webpack-merge')
const baseWebpackConfig = require('./webpack.base.conf')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
const env = process.env.NODE_ENV === 'testing'
? require('../config/test.env')
: require('../config/prod.env')
const webpackConfig = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({
sourceMap: config.build.productionSourceMap,
extract: true,
usePostCSS: true
})
},
devtool: config.build.productionSourceMap ? config.build.devtool : false,
output: {
path: config.build.assetsRoot,
filename: utils.assetsPath('js/[name].[chunkhash].js'),
chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
},
plugins: [
// http://vuejs.github.io/vue-loader/en/workflow/production.html
new webpack.DefinePlugin({
'process.env': env
}),
new UglifyJsPlugin({
uglifyOptions: {
compress: {
warnings: false
}
},
sourceMap: config.build.productionSourceMap,
parallel: true
}),
// extract css into its own file
new ExtractTextPlugin({
filename: utils.assetsPath('css/[name].[contenthash].css'),
// Setting the following option to `false` will not extract CSS from codesplit chunks.
// Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
// It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`,
// increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
allChunks: true,
}),
// Compress extracted CSS. We are using this plugin so that possible
// duplicated CSS from different components can be deduped.
new OptimizeCSSPlugin({
cssProcessorOptions: config.build.productionSourceMap
? { safe: true, map: { inline: false } }
: { safe: true }
}),
// generate dist index.html with correct asset hash for caching.
// you can customize output by editing /index.html
// see https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
filename: process.env.NODE_ENV === 'testing'
? 'index.html'
: config.build.index,
template: 'index.html',
inject: true,
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
// more options:
// https://github.com/kangax/html-minifier#options-quick-reference
},
// necessary to consistently work with multiple chunks via CommonsChunkPlugin
chunksSortMode: 'dependency'
}),
// keep module.id stable when vendor modules does not change
new webpack.HashedModuleIdsPlugin(),
// enable scope hoisting
new webpack.optimize.ModuleConcatenationPlugin(),
// split vendor js into its own file
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks (module) {
// any required modules inside node_modules are extracted to vendor
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf(
path.join(__dirname, '../node_modules')
) === 0
)
}
}),
// extract webpack runtime and module manifest to its own file in order to
// prevent vendor hash from being updated whenever app bundle is updated
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
minChunks: Infinity
}),
// This instance extracts shared chunks from code splitted chunks and bundles them
// in a separate chunk, similar to the vendor chunk
// see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
new webpack.optimize.CommonsChunkPlugin({
name: 'app',
async: 'vendor-async',
children: true,
minChunks: 3
}),
// copy custom static assets
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, '../static'),
to: config.build.assetsSubDirectory,
ignore: ['.*']
}
])
]
})
if (config.build.productionGzip) {
const CompressionWebpackPlugin = require('compression-webpack-plugin')
webpackConfig.plugins.push(
new CompressionWebpackPlugin({
asset: '[path].gz[query]',
algorithm: 'gzip',
test: new RegExp(
'\\.(' +
config.build.productionGzipExtensions.join('|') +
')$'
),
threshold: 10240,
minRatio: 0.8
})
)
}
if (config.build.bundleAnalyzerReport) {
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}
module.exports = webpackConfig
Any help would be appreciate, thanks
I'm assuming you used vuejs-templates/webpack, which does not include image optimization out of the box. You can easily add this (with imagemin-webpack-plugin) in your Webpack config:
Install ImageminWebpackPlugin with: npm i -D imagemin-webpack-plugin
In build/webpack.prod.conf.js, import the plugin, and configure it in plugins[] (after CopyWebpackPlugin):
const ImageminPlugin = require('imagemin-webpack-plugin').default;
const webpackConfig = merge(baseWebpackConfig, {
plugins: [
// ...
new ImageminPlugin({
test: /\.(jpe?g|png|gif|svg)$/i,
/* other ImageMin configs */
})
]
}
Running ImageminWebpackPlugin after CopyWebpackPlugin ensures the copied images from static are run through ImageMin optimization.
GitHub repo demo
In the current version of Vue you can use a vue.config.js that looks like this:
const ImageminPlugin = require('imagemin-webpack-plugin').default;
module.exports = {
configureWebpack: {
plugins: [
new ImageminPlugin({
disable: process.env.NODE_ENV !== 'production',
})
]
}
}
This will enable Imagemin on production builds but skip on development builds.
You can have a try. It will help you minify images automaticlly without complicated algorithm configurations. It can also help you to encode(and inline) images (behave more flexible than url-loader).
https://github.com/GaoYYYang/image-optimize-loader
module.exports = {
module: {
rules: [
{
test: /\.(png|jpe?g|webp|git|svg|)$/i,
use: [
{
loader: 'img-optimize-loader'
},
],
},
],
},
};
I have a rather large React application built with webpack 2. The application is embedded into a Drupal site as a SPA within the existing site. The Drupal site has a complex gulp build setup and I can't replicate it with webpack, so I decided to keep it.
I have split my React application into multiple parts using the DllPlugin / DllReferencePlugin combo which is shipped out of the box in webpack 2. This works great, and I get a nice vendor-bundle when building with webpack.
The problem is when I try to run my webpack configuration in gulp, I get an error. I might be doing it wrong, as I have not been able to find much documentation on this approach, but nevertheless, it's not working for me.
It looks like it's trying to include the the manifest file from my vendor-bundle before creating it.
Whenever I run one of my defined gulp tasks, like gulp react-vendor I get an error, saying that it cannot resolve the vendor-manifest.json file.
If I on other hand run webpack --config=webpack.dll.js in my terminal, webpack compiles just fine and with no errors.
I have included what I think is the relevant files. Any help on this is appreciated.
webpack.config.js
// Use node.js built-in path module to avoid path issues across platforms.
const path = require('path');
const webpack = require('webpack');
// Set environment variable.
const production = process.env.NODE_ENV === "production";
const appSource = path.join(__dirname, 'react/src/');
const buildPath = path.join(__dirname, 'react/build/');
const ReactConfig = {
entry: [
'./react/src/index.jsx'
],
output: {
path: buildPath,
publicPath: buildPath,
filename: 'app.js'
},
module: {
rules: [
{
exclude: /(node_modules)/,
use: {
loader: "babel-loader?cacheDirectory=true",
options: {
presets: ["react", "es2015", "stage-0"]
},
},
},
],
},
resolve: {
modules: [
path.join(__dirname, 'node_modules'),
'./react/src/'
],
extensions: ['.js', '.jsx', '.es6'],
},
context: __dirname,
devServer: {
historyApiFallback: true,
contentBase: appSource
},
// TODO: Split plugins based on prod and dev builds.
plugins: [
new webpack.DllReferencePlugin({
context: path.join(__dirname, "react", "src"),
manifest: require(path.join(__dirname, "react", "vendors", "vendor-manifest.json"))
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
filename: 'webpack-loader.js'
}),
]
};
// Add environment specific configuration.
if (production) {
ReactConfig.plugins.push(
new webpack.optimize.UglifyJsPlugin()
);
}
module.exports = [ReactConfig];
webpack.dll.js
const path = require("path");
const webpack = require("webpack");
const production = process.env.NODE_ENV === "production";
const DllConfig = {
entry: {
vendor: [path.join(__dirname, "react", "vendors", "vendors.js")]
},
output: {
path: path.join(__dirname, "react", "vendors"),
filename: "dll.[name].js",
library: "[name]"
},
plugins: [
new webpack.DllPlugin({
path: path.join(__dirname, "react", "vendors", "[name]-manifest.json"),
name: "[name]",
context: path.resolve(__dirname, "react", "src")
}),
// Resolve warning message related to the 'fetch' node_module.
new webpack.IgnorePlugin(/\/iconv-loader$/),
],
resolve: {
modules: [
path.join(__dirname, 'node_modules'),
],
extensions: ['.js', '.jsx', '.es6'],
},
// Added to resolve a dependency issue in this build #https://github.com/hapijs/joi/issues/665
node: {
net: 'empty',
tls: 'empty',
dns: 'empty'
}
};
if (production) {
DllConfig.plugins.push(
new webpack.optimize.UglifyJsPlugin()
);
}
module.exports = [DllConfig];
vendors.js (to determine what to add to the Dll)
require("react");
require("react-bootstrap");
require("react-dom");
require("react-redux");
require("react-router-dom");
require("redux");
require("redux-form");
require("redux-promise");
require("redux-thunk");
require("classnames");
require("whatwg-fetch");
require("fetch");
require("prop-types");
require("url");
require("validator");
gulpfile.js
'use strict';
const gulp = require('gulp');
const webpack = require ('webpack');
const reactConfig = require('./webpack.config.js');
const vendorConfig = require('./webpack.dll.js');
// React webpack source build.
gulp.task('react-src', function (callback) {
webpack(reactConfig, function (err, stats) {
callback();
})
});
// React webpack vendor build.
gulp.task('react-vendor', function (callback) {
webpack(vendorConfig, function (err, stats) {
callback();
})
});
// Full webpack react build.
gulp.task('react-full', ['react-vendor', 'react-src']);
NOTE:
If I build my vendor-bundle with the terminal with webpack --config=webpack.dll.js first and it creates the vendor-manifest.json file, I can then subsequently successfully run my gulp tasks with no issues.
This is not very helpful though, as this still will not allow me to use webpack with gulp, as I intend to clean the build before new builds run.
I ended up using the solution mentioned in the end of my question. I build my DLL file first and then I can successfully run my gulp webpack tasks.
One change that can make it easier to debug the issue, is to use the Gulp utility module (gulp-util) to show any webpack errors that might show up during build of webpack, using gulp.
My final gulp setup ended up looking like this:
gulpfile.js
'use strict';
const gulp = require('gulp');
const gutil = require('gulp-util');
const webpack = require('webpack');
const reactConfig = require('./webpack.config.js');
const vendorConfig = require('./webpack.dll.js');
// React webpack source build.
gulp.task('react', function (callback) {
webpack(reactConfig, function (err, stats) {
if (err) {
throw new gutil.PluginError('webpack', err);
}
else {
gutil.log('[webpack]', stats.toString());
}
callback();
});
});
// React webpack vendor build.
gulp.task('react-vendor', function (callback) {
webpack(vendorConfig, function (err, stats) {
if (err) {
throw new gutil.PluginError('webpack', err);
}
else {
gutil.log('[webpack]', stats.toString());
}
callback();
});
});
// React: Rebuilds both source and vendor in the right order.
gulp.task('react-full', ['react-vendor'], function () {
gulp.start('react');
});
I hope this might help someone in a similar situation.
Whenever I run one of my defined gulp tasks, like gulp react-vendor I get an error, saying that it cannot resolve the vendor-manifest.json file.
Your gulpfile.js contains this:
const reactConfig = require('./webpack.config.js');
const vendorConfig = require('./webpack.dll.js');
And webpack.config.js contains this:
new webpack.DllReferencePlugin({
context: path.join(__dirname, "react", "src"),
manifest: require(path.join(__dirname, "react", "vendors", "vendor-manifest.json"))
}),
The require() calls are currently all executed immediately. Whenever you run Gulp, it will evaluate both Webpack configuration files. As currently configured, Node runs the code in webpack.config.js at startup, and from there it sees the require() used in your creation of the DllReferencePlugin, so it will also try to read manifest.json at that time and turn it into an object...which is before it has been built.
You can solve this in one of two ways:
The DllReferencePlugin's manifest option supports either an object (which is what you are currently providing), or else a string containing the path of the manifest file. In other words, it should work if you remove the require() from around your path.join(...) call.
Alternatively, you can also defer the loading of the Webpack config files. Moving your const reactConfig = require('./webpack.config.js'); from the top of the file directly into the gulp task function should be sufficient, assuming that this function is not invoked until after the manifest has been built.
I managed to compress / compile my js and scss files with webpack. The scss file gets extracted by the 'extract-text-webpack-plugin' into an external css file. Here is the code:
var path = require('path');
var webpack = require('webpack');
var ExtractTextPlugin = require("extract-text-webpack-plugin");
require('es6-promise').polyfill();
module.exports = {
entry: ['./js/app'],
output: {
path: path.join(__dirname, 'js'),
publicPath: 'js',
filename: 'app.min.js'
},
plugins: [
new webpack.optimize.UglifyJsPlugin({
compressor: {
warnings: false,
},
}),
new webpack.optimize.OccurrenceOrderPlugin(),
new ExtractTextPlugin("../css/styles.min.css", {allChunks: false})
],
module: {
loaders: [{
test: /\.scss$/,
loader: ExtractTextPlugin.extract("style-loader", "css-loader!sass-loader")
}]
}
}
When I run now "webpack-dev-server js/app.js" - it gets my changes in the js file itself (alert for example) but does not remark changes in the css file.
This is the app.js:
var $ = require('jquery');
require('../css/styles.scss');
alert('Hi');
I guess the problem is connected to the ExtractTextPlugin. Then again I have no clue how to workaround. Any tips or ideas?
Okay, I got that going. When starting the webpack-dev-server, I'm just asking if we are in production enviroment:
const live = process.env.NODE_ENV === "production";
if(live) {
...
} else {
...
}
If we are not in production, it misses the ExtractTextPlugin out.
Finally to deploy my changes I type:
NODE_ENV=production webpack -p
One can also use a npm script to shorten this.