Closed nstoik closed 6 years ago
What does your webpack config look like?
I started with a Flask Cookiecutter template that had a starter webpack config, and then tweaked it a little bit.
Do I have to add another entry point for images? So far I have just been calling them in my jinja2 templates using the {{ asset_url_for() }}
tag.
Here is the config.
const path = require('path');
const webpack = require('webpack');
/*
* Webpack Plugins
*/
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const ManifestRevisionPlugin = require('manifest-revision-webpack-plugin');
// take debug mode from the environment
const debug = (process.env.NODE_ENV !== 'production');
// Development asset host (webpack dev server)
const publicHost = debug ? 'http://192.168.2.105:2992' : '';
const rootAssetPath = path.join(__dirname, 'assets');
module.exports = {
// configuration
context: __dirname,
entry: {
main_js: './assets/js/main',
main_css: [
path.join(__dirname, 'node_modules', 'font-awesome', 'css', 'font-awesome.css'),
path.join(__dirname, 'node_modules', 'bootstrap', 'dist', 'css', 'bootstrap.css'),
path.join(__dirname, 'node_modules', 'malihu-custom-scrollbar-plugin', 'jquery.mCustomScrollbar.css'),
path.join(__dirname, 'assets', 'css', 'style.css'),
path.join(__dirname, 'assets', 'css', 'nav-style.css'),
],
},
output: {
path: path.join(__dirname, 'fm_frontend', 'static', 'build'),
publicPath: `${publicHost}/static/build/`,
filename: '[name].[hash].js',
chunkFilename: '[id].[hash].js',
},
resolve: {
extensions: ['.js', '.jsx', '.css'],
alias:{
img: path.join(__dirname, 'assets', 'img')
},
},
devtool: 'source-map',
devServer: {
headers: { 'Access-Control-Allow-Origin': '*' },
},
module: {
rules: [
{ test: /\.html$/, loader: 'raw-loader' },
{ test: /\.less$/, loader: ExtractTextPlugin.extract({ fallback: 'style-loader', use: 'css-loader!less-loader' }) },
{ test: /\.css$/, loader: ExtractTextPlugin.extract({ fallback: 'style-loader', use: 'css-loader' }) },
{ test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: 'url-loader?limit=10000&mimetype=application/font-woff' },
{ test: /\.(ttf|eot|svg|png|jpe?g|gif|ico)(\?.*)?$/i, loader: 'file-loader?context=${rootAssetPath}&name=[path][name].[hash].[ext]' },
{ test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader', query: { presets: ['env'], cacheDirectory: true } },
],
},
plugins: [
new ExtractTextPlugin('[name].[hash].css'),
new webpack.ProvidePlugin({ $: 'jquery', jQuery: 'jquery' }),
new ManifestRevisionPlugin(path.join(__dirname, 'fm_frontend', 'webpack', 'manifest.json'), {
rootAssetPath,
ignorePaths: ['/js', '/css'],
}),
].concat(debug ? [] : [
// production webpack plugins go here
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify('production'),
}
}),
]),
};
And here is the generated manifest.json
{
"assets": {
"main_css.js": "main_css.d7c848c491f006d2119f.js",
"main_css.css": "main_css.d7c848c491f006d2119f.css",
"main_css.map": "main_css.d7c848c491f006d2119f.css.map",
"main_js.js": "main_js.d7c848c491f006d2119f.js",
"main_js.map": "main_js.d7c848c491f006d2119f.js.map"
},
"publicPath": "http://192.168.2.105:2992/static/build/"
}
Here's an example config from the test Flask app:
var path = require('path');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var ManifestRevisionPlugin = require('manifest-revision-webpack-plugin');
var rootAssetPath = './assets';
module.exports = {
entry: {
app_js: [
rootAssetPath + '/scripts/entry.js'
],
app_css: [
rootAssetPath + '/styles/main.css'
]
},
output: {
path: './build/public',
publicPath: 'http://localhost:2992/assets/',
filename: '[name].[chunkhash].js',
chunkFilename: '[id].[chunkhash].js'
},
resolve: {
extensions: ['', '.js', '.css']
},
module: {
loaders: [
{
test: /\.js$/i, loader: 'script-loader',
exclude: /node_modules/
},
{
test: /\.css$/i,
loader: ExtractTextPlugin.extract('style-loader', 'css-loader')
},
{
test: /\.(jpe?g|png|gif|svg([\?]?.*))$/i,
loaders: [
'file?context=' + rootAssetPath + '&name=[path][name].[hash].[ext]',
'image?bypassOnDebug&optimizationLevel=7&interlaced=false'
]
}
]
},
plugins: [
new ExtractTextPlugin('[name].[chunkhash].css'),
new ManifestRevisionPlugin(path.join('build', 'manifest.json'), {
rootAssetPath: rootAssetPath,
ignorePaths: ['/styles', '/scripts']
})
]
};
I haven't upgraded to Webpack 4 yet, so I'm not sure if it does anything different to resolve assets.
It looks to me like the problem is related to using Webpack 4. When I run "NODE_ENV=production webpack --progress --colors -p --mode production"
, with either of the configs, all of the assets arrive in the output directory, they are just missing in the manifest file.
I will try dig deeper and see if I can figure it out. However I am more comfortable with Python than Javascript. Any suggestion where to start? Could it be something with the format
option?
So I was able to get this working by adding extensionsRegex: /\.(ico)(\?.*)?$/i
to the ManifestRevisionPlugin configuration options.
Is this a always a required part of the configuration options? Do all assets that need to be included in the manifest.json file need to be either a Webpack entry point or be matched as part of the extensionsRegex?
That wasn't always necessary, must be something new with webpack 4. In 2.x it would just pickup everything in the root path you supply (unless you ignored the path).
It looks to be working now by explicitly including folders with desired assets via the extensionsRegex setting.
Thanks for the assistance! I really like the plugin
No problem, thanks for the feedback. It's good to know things are working pretty well with 4.x.
I am using the plugin along with flask-webpack. Everything has been working great when using the
{{ stylesheet_tag('main_css') | safe }}
or{{ javascript_tag('main_js') | safe }}
tags. But whenever I try to use{{ asset_url_for('img\favicon.ico') }}
or any other asset_url_for tag, it always resolves to None.After some debugging, I discovered that those tags are not present in the generated manifest.json file (although it appears that webpack is seeing them as the file names appear in the console when running the webpack dev server).
Is there some configuration needed to get this working? Let me know if I should share any configuration files. I am using Webpack 4 but I am not sure if this is related, as the .js and .css assets are working.
Thanks.