Symfony and Webpack Image in production - symfony

I installed webpack on my symfony project.
I do not understand the system of images and versioning, for example in the site there is a blog, and when I create a new blog post I must necessarily execute npm run dev for after having access to the new image via the folder build.
How to make this happen automatically without having to run the command each time?
const Encore = require('#symfony/webpack-encore');
// Manually configure the runtime environment if not already configured yet by the "encore" command.
// It's useful when you use tools that rely on webpack.config.js file.
if (!Encore.isRuntimeEnvironmentConfigured()) {
Encore.configureRuntimeEnvironment(process.env.NODE_ENV || 'dev');
}
Encore
// directory where compiled assets will be stored
.setOutputPath('public/build/')
.copyFiles({
from: './assets/images',
// optional target path, relative to the output dir
to: 'images/[path][name].[ext]',
// if versioning is enabled, add the file hash too
//to: 'images/[path][name].[hash:8].[ext]',
// only copy files matching this pattern
//pattern: /\.(png|jpg|jpeg)$/
})
// public path used by the web server to access the output path
.setPublicPath('/build')
// only needed for CDN's or sub-directory deploy
.setManifestKeyPrefix('build/')
/*
* ENTRY CONFIG
*
* Each entry will result in one JavaScript file (e.g. app.js)
* and one CSS file (e.g. app.css) if your JavaScript imports CSS.
*/
//Main JS
.addEntry('app', './assets/js/app.js')
.addEntry('functions', './assets/js/functions.js')
.addEntry('themepunchrevolution', './assets/rs-plugin/js/jquery.themepunch.revolution.js')
.addEntry('cookieBar', './assets/js/jquery.cookiebar.js')
//Main Css
.addEntry('style', './assets/styles/style.css')
.addEntry('blog', './assets/styles/blog.css')
.addEntry('custom', './assets/styles/custom.css')
.addEntry('extralayers', './assets/styles/extralayers.css')
.addEntry('finaltilesgallery', './assets/styles/finaltilesgallery.css')
.addEntry('flavr', './assets/styles/flavr.min.css')
.addEntry('lightbox2', './assets/styles/lightbox2.css')
.addEntry('owl_video', './assets/styles/owl.video.play.png')
.addEntry('shop', './assets/styles/shop.css')
.addEntry('timeline', './assets/styles/timeline.css')
.addEntry('setting', './assets/rs-plugin/css/settings.css')
.addEntry('setting_ie8', './assets/rs-plugin/css/settings-ie8.css')
.addEntry('vendors', './assets/styles/vendors.unminified.css')
.addEntry('bootstrap_css', './assets/styles/bootstrap.min.css')
//Admin CSS
.addEntry('app_css', './assets/styles/app.css')
.addEntry('admin', './assets/styles/admin.css')
.addEntry('default', './assets/styles/default-css.css')
.addEntry('metisMenu_css', './assets/styles/metisMenu.css')
.addEntry('responsive', './assets/styles/responsive.css')
.addEntry('slicknav_css', './assets/styles/slicknav.min.css')
.addEntry('styles', './assets/styles/styles.css')
.addEntry('typography', './assets/styles/typography.css')
.addEntry('themify', './assets/styles/themify-icons.css')
//preHome
.addEntry('preHome', './assets/styles/style_preHome.css')
.copyFiles([
{from: './node_modules/ckeditor4/', to: 'ckeditor/[path][name].[ext]', pattern: /\.(js|css)$/, includeSubdirectories: false},
{from: './node_modules/ckeditor4/adapters', to: 'ckeditor/adapters/[path][name].[ext]'},
{from: './node_modules/ckeditor4/lang', to: 'ckeditor/lang/[path][name].[ext]'},
{from: './node_modules/ckeditor4/plugins', to: 'ckeditor/plugins/[path][name].[ext]'},
{from: './node_modules/ckeditor4/skins', to: 'ckeditor/skins/[path][name].[ext]'},
{from: './node_modules/ckeditor4/vendor', to: 'ckeditor/vendor/[path][name].[ext]'}
])
// enables the Symfony UX Stimulus bridge (used in assets/bootstrap.js)
.enableStimulusBridge('./assets/controllers.json')
// When enabled, Webpack "splits" your files into smaller pieces for greater optimization.
.splitEntryChunks()
// will require an extra script tag for runtime.js
// but, you probably want this, unless you're building a single-page app
.enableSingleRuntimeChunk()
/*
* FEATURE CONFIG
*
* Enable & configure other features below. For a full
* list of features, see:
* https://symfony.com/doc/current/frontend.html#adding-more-features
*/
.cleanupOutputBeforeBuild()
.enableBuildNotifications()
.enableSourceMaps(!Encore.isProduction())
// enables hashed filenames (e.g. app.abc123.css)
.enableVersioning(Encore.isProduction())
.configureBabel((config) => {
config.plugins.push('#babel/plugin-proposal-class-properties');
})
// enables #babel/preset-env polyfills
.configureBabelPresetEnv((config) => {
config.useBuiltIns = 'usage';
config.corejs = 3;
})
// enables Sass/SCSS support
//.enableSassLoader()
// uncomment if you use TypeScript
//.enableTypeScriptLoader()
// uncomment if you use React
//.enableReactPreset()
// uncomment to get integrity="..." attributes on your script & link tags
// requires WebpackEncoreBundle 1.4 or higher
//.enableIntegrityHashes(Encore.isProduction())
//.enableVersioning()
// uncomment if you're having problems with a jQuery plugin
.autoProvidejQuery()
;
module.exports = Encore.getWebpackConfig();

You're having this issue because you are storing the user uploaded images under <project dir>/assets. That directory is private by design and not available for a client (browser). Perhaps this is why you added that copyFiles step to your configuration.
Instead of doing that you should store the uploaded images (if you want them available for rendering on a web page) somewhere under <project dir>/public (for example: <project dir>/public/uploads.
Once you do that you'll be able to access them as soon as they are uploaded either specifying the path to them or using the Twig asset function.
Example:
uploaded image is IMG001.jpg
your application stores it under <project dir>/public/uploads/IMG001.jpg
you can access it from your template using {{ asset('uploads/IMG001.jpg') }}
or in plain HTML/JS through src="/uploads/IMG001.jpg"

Related

Symfony6 - Exception: Could not find the entrypoints file from Webpack

I try to deploy my Symfony application to production.
I already ran the command:
yarn encore prod
I still see the following exception:
An exception has been thrown during the rendering of a template ("Could not find the entrypoints file from Webpack: the file "/home/mobil/public_html/public/build/entrypoints.json" does not exist.").
How can I resolve my issue?
If i'ts a shared hosting, I think i'ts because the setPublicPath configuration.
I had a smillar problem before, the assets works in local but not on server and the solution was to make tow webpack configurations, on for local and the second for prod
https://symfony.com/doc/current/frontend/encore/advanced-config.html#defining-multiple-webpack-configurations
Encore
// directory where compiled assets will be stored
.setOutputPath('public/build/')
.setPublicPath('/build') // local config
.setManifestKeyPrefix('build/')
// ........
})
;
const localConfig = Encore.getWebpackConfig();
localConfig.name = 'localConfig';
// reset Encore to build the second config
Encore.reset();
Encore
// directory where compiled assets will be stored
.setOutputPath('public/build/')
.setPublicPath('/public/build') // for prod on shared hosting
.setManifestKeyPrefix('build/')
// .....
// build the second configuration
const prodConfig = Encore.getWebpackConfig();
// Set a unique name for the config (needed later!)
prodConfig.name = 'prodConfig';
// export the final configuration as an array of multiple configurations
module.exports = [localConfig, prodConfig];
the commands for each config:
./node_modules/.bin/encore dev --config-name localConfig
./node_modules/.bin/encore prod --config-name prodConfig

Cannot get / with encore dev-server in Symfony

I would like to point out that I am on a classic Symfony application with the default configuration for Webpack. And that the watch command works very well.
Hello,
When I try to start the Webpack Encore development server, the compilation is done without any problem but when I access the page, I get the error "Cannot GET /". I have no errors in the console
(source: casimages.com)
But interestingly, http://localhost:8000/webpack-dev-server seems to work.
(source: casimages.com)
var Encore = require('#symfony/webpack-encore');
if (!Encore.isRuntimeEnvironmentConfigured()) {
Encore.configureRuntimeEnvironment(process.env.NODE_ENV || 'dev');
}
Encore
// directory where compiled assets will be stored
.setOutputPath('public/build/')
// public path used by the web server to access the output path
.setPublicPath('/build')
// only needed for CDN's or sub-directory deploy
//.setManifestKeyPrefix('build/')ne CSS file (e.g. app.css) if your JavaScript imports CSS.
*/
.addEntry('app', './assets/js/app.js')
//.addEntry('page1', './assets/js/page1.js')
//.addEntry('page2', './assets/js/page2.js')
.splitEntryChunks()
.enableSingleRuntimeChunk()
.cleanupOutputBeforeBuild()
.enableBuildNotifications()
.enableSourceMaps(!Encore.isProduction())
// enables hashed filenames (e.g. app.abc123.css)
.enableVersioning(Encore.isProduction())
.configureBabel(() => {}, {
useBuiltIns: 'usage',
corejs: 3
})
//.enableSassLoader()
//.enableTypeScriptLoader()
//.enableIntegrityHashes(Encore.isProduction())
.autoProvidejQuery()
.autoProvideVariables({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery',
})
.enableReactPreset()
;
module.exports = Encore.getWebpackConfig();
I got "Cannot GET /" when trying to reach the server through localhost. Finally Iil I let Symfony open the webpage with the command:
symfony open:local
It opened on https://127.0.0.1:8000
You can check if your files are created in public/build folder. If your files are created completely check if they have appropriate access to read.

Symfony Encore multiple asset manifests

I have a question regarding Encore in Symfony 3.4 and asset versioning.
In my webpack.config.jsI have two configurations.
First is for JS files, the other one for compiling .less.
Each configuration is reset by Encore.reset()
Output bundles are generating manifest with versioning via .enableVersioning, so I have two manifest.json in
web/js/manifest.json
web/stylesheets/manifest.json
According to docs, to have my assets loaded via manifest I need to declare it in config.yml
assets:
base_path: "%myapp.http.site_assets_suffix%"
stylesheets:
json_manifest_path: "%kernel.project_dir%/web/assets/stylesheets/manifest.json"
If I want to link to style.css generated by webpack, I use
asset("stylesheets/style.css")
But in my application I have two manifests and I think this can't be changed due to two Encore configurations.
I've tried adding something in likes of
packages:
stylesheets:
json_manifest_path: "%kernel.project_dir%/web/assets/stylesheets/manifest.json"
js:
json_manifest_path: "%kernel.project_dir%/web/assets/js/manifest.json"
because I saw that somewhere, but unfortunately this won't work at all.
I've thought about combining two manifests into one in last webpack entry point, but this can be time consuming.
Is there any other solution than combining manfiests or combining js + less compilation into one big Encore task?
I've found a solution
assets:
base_path: 'path%'
packages:
noversion:
version: false
version_format: "%%1$s"
base_path: "path%"
stylesheets:
json_manifest_path: "%kernel.project_dir%/web/assets/stylesheets/manifest.json"
js:
json_manifest_path: "%kernel.project_dir%/web/assets/js/manifest.json"
admin:
json_manifest_path: "%kernel.project_dir%/web/assets/js/admin/manifest.json"
And then in .twig files, you need to call it as
<script src="{{ asset('assets/DIRNAME/WEBPACK_ENTRY_NAME_HERE', ASSET_PACKAGE_NAME_HERE) }}"></script>
In my case
<script src="{{ asset('assets/js/backend.js', 'js') }}"></script>
Where WEBPACK_ENTRY_NAME is the name of the Webpack/Encore bundle from webpack.config.js, in my case
.setOutputPath('./web/assets/js')
.setPublicPath('/assets/js')
.addEntry('backend',
Sorry for delayed answer, but I forgot about it.
Webpack Encore use webpack-manifest-plugin to generate manifest.json file.
According to the doc, you can specify an options.seed when you setup your config.
A cache of key/value pairs to used to seed the manifest. This may include a set of custom key/value pairs to include in your manifest, or may be used to combine manifests across compilations in multi-compiler mode. To combine manifests, pass a shared seed object to each compiler's ManifestPlugin instance.
Encore.configureManifestPlugin(options => {
let seed;
try {
// require your existing manifest content if exists
seed = require(path.join(outputPath, 'manifest.json'));
}
catch (e) {
// fallback if manifest.json is missing
seed = {};
}
// inject your latest config as seed.
// The plugin will update it and rewrite manifest.json with correct values (overwrite existing keys, append news)
options.seed = seed;
// Also i add a trick to avoid "License.txt" entries
options.generate = function(seed, files, entrypoints) {
// trick to avoid generate useless versionned entries like License
const filesWithoutLicense = files.filter(file => {
return file.path.match(/.*LICENSE.*/) === null;
});
const newManifestContent = filesWithoutLicense.reduce(
(newManifestContent, file) => {
newManifestContent[file.name] = file.path;
return newManifestContent;
},
seed
);
return newManifestContent;
}

Symfony Encore/Webpack never completes

Anytime I try to run encore, it doesn't complete and hangs at...
$ /vagrant/app/node_modules/.bin/encore dev
Running webpack ...
I've removed node_modules and re-installed numerous times following the Symfony documentation. Tried using only npm and also tried only using yarn. Any suggestions would be much appreciated. I've included package.json and webpack.config.js, if there is anything else needed to help troubleshoot, please let me know.
package.json
{
"devDependencies": {
"#symfony/webpack-encore": "^0.20.1",
"node-sass": "^4.9.0",
"sass-loader": "^7.0.3"
}
}
webpack.config.js
var Encore = require('#symfony/webpack-encore');
Encore
// the project directory where compiled assets will be stored
.setOutputPath('public/build/')
// the public path used by the web server to access the previous directory
.setPublicPath('/app/build')
.setManifestKeyPrefix('build')
.cleanupOutputBeforeBuild()
.enableSourceMaps(!Encore.isProduction())
// uncomment if you use Sass/SCSS files
.enableSassLoader()
// uncomment to create hashed filenames (e.g. app.abc123.css)
// .enableVersioning(Encore.isProduction())
// uncomment to define the assets of the project
// .addEntry('js/app', './assets/js/app.js')
.addStyleEntry('css/style', './assets/sass/style.scss')
// .addStyleEntry('css/print', './assets/sass/print.scss')
// uncomment for legacy applications that require $/jQuery as a global variable
// .autoProvidejQuery()
;
module.exports = Encore.getWebpackConfig();
I figured out the issue. I had to disable the resolveUrlLoader in my sass loader options.
.enableSassLoader(function(options) {}, {
resolveUrlLoader: false
})

JASMINE not defined when I try to run Karma test runner

I am trying to hook up the Karma test runner, using this seed project as a model.
I pull the seed project in, build it, and the test runner works great.
When I edit the karma.conf.js config file to start including the files from my project, and move it to my current setup (outside the seed project), I get this error:
Running "karma:dev" (karma) task
ERROR [config]: Error in config file!
[ReferenceError: JASMINE is not defined]
ReferenceError: JASMINE is not defined
at module.exports (C:\dev_AD_2014.01_PHASE1\config\karma-dev.conf.js:4:7)
...
I think I see what it's complaining about... in the seed project, it's karma config file is of an older format, that must have JASMINE and JASMINE_ADAPTER defined somewhere:
Seed Project karma config snippet
files = [
JASMINE,
JASMINE_ADAPTER,
'../app/lib/angular/angular.js',
'lib/angular/angular-mocks.js',
'../app/js/*.js',
....
];
exclude = ['karma.conf.js'];
...
My newer setup uses all the latest grunt plugins, and wants the config file wrapped in a module definition like so:
My karma config snippet
module.exports = function(config) {
config.set({
files: [
JASMINE,
JASMINE_ADAPTER,
// library and vendor files
'../dev/vendor/**/*.js'
'../dev/app/**/*.js'
],
exclude: ['**/*.e2e.js', '../config/*.js'],
reporters: ['progress'],
...
So it seems the problem is clear: the newer version(s) of some grunt plugins expect the modular definition, but are longer is setting up JASMINE, etc, as variables that are defined. That's my guess, but I'm a little lost on how to resolve this. I don't want to use the version of Karma that comes with the seed project if I can help it... I think it's version 0.4.4. I believe the newest stable version is 0.10.x.
What am I doing wrong?
Thanks!
If you want to use the latest stable Karma version (0.10.9) you should define Jasmine in the frameworks section and be sure to have karma-jasmine in the plugins section, in your karma configuration file.
Here's an example config file:
karma.conf.js
module.exports = function(config){
config.set({
// base path, that will be used to resolve files and exclude
basePath: '',
// list of files / patterns to load in the browser
files: [
{pattern: 'app/**/*.js', watched: true, included: true, served: true}
],
// list of files to exclude
exclude: [
],
preprocessors: {
},
proxies: {
},
// test results reporter to use
// possible values: 'dots', 'progress', 'junit', 'growl', 'coverage'
reporters: ['progress'],
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,
autoWatch: true,
// frameworks to use
frameworks: ['jasmine'],
// Start these browsers, currently available:
// - Chrome
// - ChromeCanary
// - Firefox
// - Opera
// - Safari (only Mac)
// - PhantomJS
// - IE (only Windows)
browsers: [
'Chrome'
],
plugins: [
'karma-chrome-launcher',
'karma-firefox-launcher',
'karma-script-launcher',
'karma-jasmine'
],
// If browser does not capture in given timeout [ms], kill it
captureTimeout: 60000,
// Continuous Integration mode
// if true, it capture browsers, run tests and exit
singleRun: false
});
};
Source: Karma-runner docs
Including JASMINE and JASMINE_ADAPTER in the files array is applicable to Karma versions 0.8.x and down. With newer versions of Karma, that is version 0.13 currently, just remove those 2 lines from the files array since you are already loading Jasmine as the framework(framework=['jamsine']).

Resources