Open jthomaschewski opened 9 years ago
I have exactly the same problem. Css loader in prod is resolving backgrounds to the assets/...
path, which is not visible in prod. The possible solution is to put CSS files in the meteor_core directoy, losing the hot code push ... not optimal ;(
can you paste your dev and prod webpack config?
@jbbr have you changed path
or publicPath
anywhere in your webpack config? In this project the assets should be saved to /assets/...
I can reproduce this with the latest master:
{ test: /\.jpg$/, loader: 'file' },
import image from '../images/image.jpg';
....
<img src={image} />
....
src="http://0.0.0.0:9090/assets/44bae156f12e5089150d096a2cbf83c1.jpg"
When using ./prod:
Image url does not exist.
result src="/assets/44bae156f12e5089150d096a2cbf83c1.jpg"
(http://127.0.0.1:3000/assets/44bae156f12e5089150d096a2cbf83c1.jpg
)
The file exists in webpack/assets/
but is not shipped by the meteor server in ./prod mode.
Bad workaround: symbolic link from meteor_core/public/assets
to webpack/assets
. But then also server.bundle.js
is published to the world...
@jbbr thought I had commented, we can solve this by simply making different asset directories for server and client (or even just outputting straight into the Meteor dirs)
Errr...but Meteor very unfortunately would auto-load the client.bundle.js from the asset directory as well. Maybe we'll have to go with a package.
Actually I think I can solve with separate client and server output dirs, and making meteor_core/client
a symlink to webpack's client output directory.
Yesterday I was experimenting with webpack-dev-server
's proxy: { '*': 'http://localhost:3000' }
option, hoping I would be able to open the webpage from localhost:9090
, but unfortunately Meteor's sockjs
wasn't connecting...didn't too much surprise me...
I solved it.
1.Add folder /meteor_core/public
2.modify prod.js
require('shelljs/global');
if (!process.env.NODE_ENV) {
process.env.NODE_ENV = env.NODE_ENV = 'production';
}
var fs = require('fs');
var path = require('path');
var dirs = require('./dirs');
var webpack = require('webpack');
var addProgressPlugin = require('./addProgressPlugin');
var statsOptions = require('./statsOptions');
var serverConfig = require(path.join(dirs.webpack, 'webpack.config.server.prod'));
var clientConfig = require(path.join(dirs.webpack, 'webpack.config.client.prod'));
addProgressPlugin(serverConfig);
addProgressPlugin(clientConfig);
serverConfig.plugins.push(new webpack.BannerPlugin('var require = Npm.require;\n', {raw: true}));
var serverBundlePath = path.join(dirs.assets, 'server.bundle.js');
var clientBundlePath = path.join(dirs.assets, 'client.bundle.js');
var serverBundleLink = path.join(dirs.meteor, 'server/server.bundle.min.js');
var clientBundleLink = path.join(dirs.meteor, 'client/client.bundle.min.js');
var loadClientBundleHtml = path.join(dirs.webpack, 'loadClientBundle.html');
var loadClientBundleLink = path.join(dirs.meteor, 'client/loadClientBundle.html');
var requireServerBundleJs = path.join(dirs.meteor, 'server/require.server.bundle.js');
var clientAssetsPath = dirs.assets; //add
var clientAssetsLink = path.join(dirs.meteor, 'public/assets'); //add
exec('node core-js-custom-build.js');
if (fs.existsSync(loadClientBundleLink)) rm(loadClientBundleLink);
if (fs.existsSync(requireServerBundleJs)) rm(requireServerBundleJs);
var serverCompiler = webpack(serverConfig);
var serverBundleReady = false;
var clientBundleReady = false;
serverCompiler.watch(serverConfig.watchOptions || {}, function(err, stats) {
console.log(stats.toString(statsOptions));
if (!serverBundleReady) {
serverBundleReady = true;
ln('-sf', serverBundlePath, serverBundleLink);
compileClient();
}
});
function compileClient() {
var clientCompiler = webpack(clientConfig);
clientCompiler.watch(clientConfig.watchOptions || {}, function(err, stats) {
console.log(stats.toString(statsOptions));
if (!clientBundleReady) {
clientBundleReady = true;
ln('-sf', clientBundlePath, clientBundleLink);
ln('-sf', clientAssetsPath, clientAssetsLink); // add
runMeteor();
}
});
}
function runMeteor() {
cd(dirs.meteor);
exec('meteor run --production --settings ../settings/prod.json', {async: true});
}
Warning: the above is likely insecure.
@TeemoWan That assets folder also includes your server.bundle.js
file. This approach will expose that to anyone who knows what to look for. That file will contain all your server-only code, which should likely remain secret.
I came up with a slightly safer way of doing the same thing. It white-lists some static file types and only symlinks those. It seems like there should be a more elegant solution, but this gets the job done without too much hassle.
Some constants.
var staticAssetPath = path.join(dirs.meteor, 'public/assets');
var staticAssetWhitelist = ['png', 'jpg', 'svg', 'eot', 'woff', 'ttf', 'woff2'];
And for the linking: put the following in the compileClient
callback right before runMeteor()
in prod.js
or return callback();
in deploy.js
.
fs.readdirSync(dirs.assets).filter(function(file) {
return staticAssetWhitelist.indexOf(file.split('.').slice(-1)[0].toLowerCase()) != -1;
}).forEach(function(staticFile) {
ln('-sf', path.join(dirs.assets, staticFile), path.join(staticAssetPath, staticFile));
});
@defrex That should work for an unchanging list of static assets, but if you add a new asset, you'd need to restart prod.js, right? Any downsides to running this even when clientBundleReady is set?
@bpartridge It shouldn't matter. You'll need to attach it to a file watcher or something if you don't want to restart the script.
I'm trying to load some images via webpack by using
url-loader
like that:{ test: /\.png$/, loader: 'url-loader?limit=10000&mimetype=image/png' }
In
dev
mode imported images get converted to a url likehttp://0.0.0.0:9090/assets/7de2d4d25d8c70839ae06de9c36ed886.png
which seems to be correct. But the webpack-dev server returns an empty response. No files are generated anywhere in ./webpack/assets or ./meteor_coreIn
prod
mode imported images are generated and saved to e.g./webpack/assets/7de2d4d25d8c70839ae06de9c36ed886.png
But urls point to meteor server like http://127.0.0.1:3000/assets/7de2d4d25d8c70839ae06de9c36ed886.png and obviously the generated files are not accessible.
Of course it's possible to access images which are stored in
./meteor_core/public/
- but I'd like to use webpack loaders to have goodies like automatically generated base64 strings for small images, minification...Is there any recommended way of loading assets by url with this skeleton?