symfony / webpack-encore

A simple but powerful API for processing & compiling assets built around Webpack
https://symfony.com/doc/current/frontend.html
MIT License
2.23k stars 199 forks source link

Symfony, webpack, on click event executed double times only in prod enviroment #845

Open shubaivan opened 4 years ago

shubaivan commented 4 years ago

I use symfony/framework-bundle 5.0.5 and "symfony/webpack-encore-bundle": "dev-master" When I develop code in dev env was everything correct, but when switched project to prod enviroment I faced with strange behaviour, my on lick event executed two times, maybe some double including js script I don't understand, when I returned to dev env problem was gone. How to correct use web pack in symfony framework in prod env ?

webpack.config.js

var 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/')
    // 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
     *
     * Add 1 entry for each "page" of your app
     * (including one that's included on every page - e.g. "app")
     *
     * 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.
     */
    .addEntry('app', './assets/js/app.js')
    .addEntry('index/js/index.min', './assets/js/index/index.js')
    .addEntry('index/js/awin.min', './assets/js/index/awin.js')
    .addEntry('index/js/adtraction.min', './assets/js/index/adtraction.js')
    .addEntry('index/js/adrecord.min', './assets/js/index/adrecord.js')
    .addEntry('index/js/tradeDoubler.min', './assets/js/index/tradeDoubler.js')
    .addEntry('index/js/hover_menu.min', './assets/js/index/hover_menu.js')
    .addEntry('index/js/brand_list.min', './assets/js/index/brand_list.js')
    .addEntry('index/js/admin_shop_rule_list.min', './assets/js/index/admin_shop_rule_list.js')
    .addEntry('index/js/resource_shop_list.min', './assets/js/index/resource_shop_list.js')
    .addEntry('index/js/statisticsMonitoring.min', './assets/js/index/statisticsMonitoring.js')

    //.addEntry('page1', './assets/js/page1.js')
    //.addEntry('page2', './assets/js/page2.js')

    // 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())

    // enables @babel/preset-env polyfills
    .configureBabelPresetEnv((config) => {
        config.useBuiltIns = 'usage';
        config.corejs = 3;
    })

    // enables Sass/SCSS support
    .enableSassLoader()
    .addStyleEntry('index/css/index.min', './assets/css/app.scss')

    // uncomment if you use TypeScript
    //.enableTypeScriptLoader()

    // uncomment to get integrity="..." attributes on your script & link tags
    // requires WebpackEncoreBundle 1.4 or higher
    //.enableIntegrityHashes(Encore.isProduction())

    // uncomment if you're having problems with a jQuery plugin
    .autoProvidejQuery()

    // uncomment if you use API Platform Admin (composer req api-admin)
    //.enableReactPreset()
    //.addEntry('admin', './assets/js/admin.js')
;

module.exports = Encore.getWebpackConfig();

config/packages/prod/webpack_encore.yaml

webpack_encore:
#     Cache the entrypoints.json (rebuild Symfony's cache when entrypoints.json changes)
#     Available in version 1.2
    cache: true

config/packages/webpack_encore.yaml

webpack_encore:
    # The path where Encore is building the assets - i.e. Encore.setOutputPath()
    output_path: '%kernel.project_dir%/public/build'

my base twig template has script only for fosjsrouting

{% block javascripts %}

    <script src="{{ asset('bundles/fosjsrouting/js/router.min.js') }}"></script>
    <script src="{{ path('fos_js_routing_js', { callback: 'fos.Router.setData' }) }}"></script>

{% endblock %}

and my child template whe I faced with double click

{% extends 'base.html.twig' %}
//...///
{% block javascripts %}
    {{ parent() }}
    {{ encore_entry_script_tags('index/js/resource_shop_list.min') }}

    <script>
        function getJSonObject(value) {
            return $.parseJSON(value.replace(/&quot;/ig, '"'));
        }

        let th_keys = getJSonObject("{{ dataTbaleKeys ? dataTbaleKeys|json_encode() : "{}" }}");
        let for_prepare_defs = getJSonObject("{{ dataTbaleKeys ? dataTbaleKeys|json_encode() : "{}" }}");

    </script>

{% endblock %}

and my assets/js/index/resource_shop_list.js

/*
 * Welcome to your app's main JavaScript file!
 *
 * We recommend including the built version of this JavaScript file
 * (and its CSS file) in your base layout (base.html.twig).
 */

// any CSS you import will output into a single css file (app.css in this case)
import '../../css/app.scss';
import * as dt_bs4 from 'datatables.net-bs4'
import * as fh_bs from 'datatables.net-fixedheader-bs4';
import * as r_bs from 'datatables.net-responsive-bs4';

require('@fortawesome/fontawesome-free/css/all.min.css');
require('datatables.net-dt/css/jquery.dataTables.min.css');
require('datatables.net-fixedheader-bs4/css/fixedHeader.bootstrap4.min.css');
require('datatables.net-responsive-bs4/css/responsive.bootstrap4.min.css');

require('@fortawesome/fontawesome-free/js/all.js');

const $ = require('jquery');
global.$ = global.jQuery = $;
// import 'popper.js';
require('bootstrap');

document.addEventListener("DOMContentLoaded", function () {
    console.log("resource shop list!");
    const body = $('body');
    const app_rest_admin_resourceshops_shopreloading = window.Routing.generate('app_rest_admin_resourceshops_shopreloading');
    var table;
    body.on('click', '.resource_reloading button', function () {
        let current = $(this);
        console.log(current);

        let shopName = current.data('shopName');

        reloadingShop(shopName);
    });

    // ...//

I double checked, I crete event only one time and in dev env it's worked correct. For prod env in server I executed

php bin/console c:c && yarn encore production && chmod 777 -R
 var/cache/ var/log/

with result

Done in 13.51s.

How to resolv it ?

BurningDog commented 4 years ago

Are you including resource_shop_list.js in any of your other javascript files, especially app.js?

shubaivan commented 4 years ago

no, I checked it, fiile assets/js/index/resource_shop_list.js stand alone and he is included to my html, by

    {{ encore_entry_script_tags('index/js/resource_shop_list.min') }}

I double check everything, and the most strange behaviour this is when project use dev env I did not faced with double click

###> symfony/framework-bundle ###
APP_ENV=dev

when switch to APP_ENV=prod - faced with problem. I will recheck everything again

Chrysweel commented 3 years ago

I have a similar issue.

In my template twig I have {{ encore_entry_script_tags('assets/pages/course/single') }} and in my javascript I have:

document.addEventListener('DOMContentLoaded', () => {
    console.log('hello');
});

And this console.log execute two times.

If I change the encore_entry_script_tags to <script src="{{ asset('build/assets/pages/course/single.js') }}"></script> the console.log only show one time... any idea??

@shubaivan Did you fix your mistake?

Kocal commented 3 years ago

That's a really weird issue. What is the trace of the two console.log?

Chrysweel commented 3 years ago

Hello @Kocal, thanks for to reply.

trace?

I see in console.log two "hello" ... I think that dont understand your question, the js file is very simple..

Kocal commented 3 years ago

Hey, my bad, I thought that you could have seen easily in the web console without touching your code.

Can you modifiy your console.log() to console.trace(), open the web console and gave us the call traces?

Chrysweel commented 3 years ago

Hello this help?

imagen

Chrysweel commented 3 years ago

This is my composer.json

"require": {
        "php": "^7.4",
        "twig/extensions": "~1.5",
        "twig/twig": "~2.12",
        "sensio/framework-extra-bundle": "^5.5",
        "frequence-web/contact-bundle": "dev-update/sf-4",
        "jms/serializer-bundle": "~2.4",
        "sylius/sylius": "^1.8",
        "doctrine/collections": "~1.6",
        "doctrine/doctrine-bundle": "1.12.x-dev#c294d32304cd57e732617ee961cc82973c033235",
        "doctrine/doctrine-cache-bundle": "~1.4",
        "doctrine/doctrine-migrations-bundle": "~3.0",
        "doctrine/orm": "~2.7",
        "doctrine/dbal": "2.11.*",
        "presta/sitemap-bundle": "~2.0",
        "excelwebzone/recaptcha-bundle": "~1.5",
        "aws/aws-sdk-php": "^3.133",
        "crevillo/payum-redsys": "dev-fix-unauthorized",
        "php-http/guzzle6-adapter": "^2.0",
        "predis/predis": "^1.1",
        "snc/redis-bundle": "^3.2",
        "knplabs/knp-gaufrette-bundle": "~0.5",
        "lexik/jwt-authentication-bundle": "~2.6",
        "aporat/store-receipt-validator": "^3.4",
        "nelmio/api-doc-bundle": "^3.6",
        "eightpoints/guzzle-bundle": "^7.6",
        "nelmio/cors-bundle": "^1.5",
        "maxbanton/cwh": "v1.1.*",
        "ekino/newrelic-bundle": "^2.2",
        "symfony/web-profiler-bundle": "^4",
        "symfony/webpack-encore-bundle": "^1.7",
        "sylius/plus": "^0.30.0",
        "symfony/flex": "^1.9",
        "symfony/asset": "^4",
        "symfony/orm-pack": "^1.0",
        "symfony/twig-pack": "^1.0",
        "symfony/monolog-bundle": "^3.5",
        "symfony/mailer": "^4",
        "symfony/form": "^4",
        "symfony/security-bundle": "^4",
        "symfony/translation": "^4",
        "symfony/validator": "^4",
        "sylius/shop-api-plugin": "v1.0.0-beta.21",
        "symfony/dotenv": "^4",
        "salesforce-mc/fuel-sdk-php": "dev-master#44c87189737962b09c6e9faf2059a493e9b36523",
        "egulias/email-validator": "^2.1",
        "zendesk/zendesk_api_client_php": "^2.2",
        "cebe/php-openapi": "^1.4",
        "symfony/web-link": "4.4.*",
        "justinrainbow/json-schema": "^5.2"
    },
    "require-dev": {
        "symfony/var-dumper": "*",
        "fzaninotto/faker": "~1.8",
        "phpunit/phpunit": "^8.0",
        "phpunit/php-file-iterator": "2.*",
        "symfony/phpunit-bridge": "*",
        "sensiolabs/security-checker": "^5.0",
        "symfony/profiler-pack": "^1.0",
        "symfony/maker-bundle": "^1.14",
        "doctrine/doctrine-fixtures-bundle": "^3.3",
        "symfony/debug-bundle": "^4",
        "symfony/browser-kit": "^4",
        "symfony/css-selector": "^4",
        "hautelook/alice-bundle": "^2.7",
    "dama/doctrine-test-bundle": "^6.3",
    "nelmio/alice": "^3.5"
    },
    "scripts": {
        "post-install-cmd": [
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::buildBootstrap"
        ],
        "post-update-cmd": [
            "Incenteev\\ParameterHandler\\ScriptHandler::buildParameters",
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::buildBootstrap"
        ],
        "auto-scripts": {
            "cache:clear": "symfony-cmd",
            "assets:install %PUBLIC_DIR%": "symfony-cmd",
            "security-checker security:check": "script"
        }
    },

And my config of webpack.

const Encore = require('@symfony/webpack-encore');
const path = require('path');

Encore
    .setOutputPath('public/build/')

    .setPublicPath('/build')

    .addEntry('assets/pages/course/single', './assets/v3/js/pages/course/single/single.js')
    (...)

    .addLoader({
        test: /\.html$/,
        exclude: /node_modules/,
        loader: 'html-loader'
    })

    .addAliases({
        // Old design
        scss: path.resolve(__dirname, './assets/scss/'),
        js: path.resolve(__dirname, './assets/js/'),
        // New design
        scss3: path.resolve(__dirname, './assets/v3/scss/'),
        js3: path.resolve(__dirname, './assets/v3/js/')
    })

    .configureFilenames({
      js: '[name].js?[contenthash:16]',
      css: '[name].css?[contenthash:16]'
    })

    .enableSourceMaps(!Encore.isProduction())

    .copyFiles([
        { from: './assets/static' , to: 'static/[path][name].[ext]' }, // Old design
        { from: './assets/v3/static' , to: 'assets/[path][name].[ext]' }, // New design
    ])
    .enableSingleRuntimeChunk()
    .autoProvidejQuery()

    .enableSassLoader(function(options) {
            options.includePaths = [ 'assets/scss/', 'node_modules/' ]
        }
    )
    .enablePostCssLoader()
    .enableBuildNotifications()
    .cleanupOutputBeforeBuild()

const webpackConfig = Encore.getWebpackConfig();

webpackConfig.stats = "errors-only";

module.exports = webpackConfig;
quentint commented 2 years ago

Hi @shubaivan,
did you manage to fix this?

I'm experiencing the same issue where <script src="/build/runtime.[something].js"></script> is injected twice (once in the <head>, once near the </body>), that makes all encore_entry_script_tags-called scripts being executed twice 🙁

quentint commented 2 years ago

Hoping it could help someone else, here's the reason of my own issue: https://github.com/symfony/webpack-encore-bundle/issues/166

carsonbot commented 1 week ago

Thank you for this issue. There has not been a lot of activity here for a while. Has this been resolved?