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 197 forks source link

PHPStorm integration #236

Closed plfort closed 5 years ago

plfort commented 6 years ago

PHPStorm can interpret standart Webpack config file but not the Encore webpack.config.js :

Can't analyse webpack.config.js: coding assistance will ignore module resolution rules in this file. Possible reasons: this file is not a valid webpack configuration file or its format is not currently supported by the IDE

I made this workaround to handle this : https://gist.github.com/plfort/93da0ee1465f1d7f929fe5d9e6307532

Do you have a better solution ?

weaverryan commented 6 years ago

Hey there!

I’m aware of this issue... but I think it’s not an issue (but it is confusing people). As far as I understand it, phpstorm has support to analyze you mr wepback.config.js file, which can help if you’re writing it by hand. But Encore generates this confgi for you, so I don’t think there’s any benefit to the phpstorm analysis anyways when using Encore. In other words, the warning should just be ignored.

Does the Phpstorm analysis give you any useful functionality with your workaround? Or is it just a way to make the earning disappear?

plfort commented 6 years ago

PHPStorm can resolve modules with my workaround : https://www.jetbrains.com/help/phpstorm/webpack.html#webpack_module_resolution This is really helpful when working with aliases

weaverryan commented 6 years ago

Ah, so it uses the roots and aliases. Hmm, interesting. I don’t know if we can fix this or not, but it’s a legit issue.

anurbol commented 6 years ago

This is most probably PHPStorm 2017.3.{~3} issue. Maybe a bug.

If you want to get rid of this problem you can remove the notifications & log for the Webpack from Settings->Apperance&Behavior->Notifications->Webpack

https://stackoverflow.com/a/48562153/9259778

florentdestremau commented 6 years ago

I don't have the autocomplete for the Encore library. Not very damaging but a bit annoying, i need to Ctrl + click on the require('@symfony/webpack-encore'); to get a list of all the methods and explore the plugin by hand.

Is there a link with this issue ?

Lyrkan commented 6 years ago

@florentdestremau Nop, that's not related to this issue but to #151.

Aerendir commented 6 years ago

This is definitely an annoying issue.

The trick suggested by @plfort works great (after changing the default webpack.config.js to fakewebpackconfig.js in Preferences > Languages & Framework > JavaScript > Webpack.

Maybe Encore can create the file using a method like .createFakeConfigForPHPStorm but I understand its name is really coupled with the PHPStorm editor and that this trick maybe useful in other editors too...

Lyrkan commented 6 years ago

@Aerendir I'm not sure that's something we could add...

The issue with that workaround is that calling JSON.stringify() on the Webpack config object won't necessarily produce a valid configuration file (for instance if it contains functions... which is almost always the case if you use plugins).

That "fake" config may be valid today for PHPStorm if it only looks for some keys but we can't guarantee that'll always be the case.

Aerendir commented 6 years ago

@Lyrkan , ok, so there are some drawbacks!

I was not aware of this...

For the moment it works, with an Encore produced configuration and some minor tweaks that anyway don't involves the use of functions...

Maybe in future I will need them and then I will know why the integration will be broken!

Thank you!

plfort commented 6 years ago

Yes it is a quick & dirty hack... One possible solution would be to generate a valid webpack configuration file from Encore configuration.

Aerendir commented 6 years ago

Unfortunately I have not the javascript experience required to do this :( I'm still learning all this stuff like React, redux and all the ecosystem... and also the javascript development basics as it is really different from the PHP development...

stof commented 6 years ago

well, making Encore generate a config file doing its own new ...Plugin instead of building the config would be very tricky (and requires rethinking the way Encore is used as it does not fit anywhere in the current API AFAICT)

Aerendir commented 6 years ago

@stof , yes, I was thinking just at this...

And I consider also that if someone comes with a more complex configuration, than we can also assume (s)he doesn't need Encore at all.

Or at lest (s)he can use the trick above to generate the initial "static" configuration to then further tweak...

Something really similar to what happen when react-create-app and then eject...

So, maybe a method eject maybe something to think about?

Aerendir commented 6 years ago

Or also a simple note in the documentation?

plfort commented 6 years ago

Too dirty to be in the documentation IMOO

weaverryan commented 6 years ago

Maybe someone can talk to the PhpStorm people?

If phpstorm only uses this to resolve roots and aliases, then possibly we could generate a config with at least that correct. But I’d want phpstorm to be able to find that config file automatically - needing to do all this config in Encore or in phpstorm is a pain. I mostly want the warning to go away because it confuses people :)

Aerendir commented 6 years ago

@weaverryan, not only it is confusing, it also shows errors in files when using web pack specific configurations as, for example, when using absolute paths configured in the resolve node of the configuration.

So it is really something that limit the development capabilities...

eman1986 commented 6 years ago

I created a ticket on it for them, I've seen other people complain about it and I even notice it when I'm not using encore.

https://youtrack.jetbrains.com/issue/WI-42377

soullivaneuh commented 6 years ago

@plfort I did try your solution without success. Here is my complete config file:

const
  CopyWebpackPlugin = require('copy-webpack-plugin'),
  Encore = require('@symfony/webpack-encore'),
  UglifyJsPlugin = require('uglifyjs-webpack-plugin'),
  fs = require('fs'),
  path = require('path'),
  webpack = require('webpack');

Encore
  .setOutputPath('public/build/')
  .setPublicPath('/build')
  .cleanupOutputBeforeBuild()
  .addEntry('app', './assets/js/app.js')
  .addEntry('front', './assets/js/front.js')
  .addEntry('login', './assets/js/login.js')
  .addEntry('admin', './assets/js/admin.js')
  .addEntry('common', './assets/js/common.js')
  .addPlugin(new CopyWebpackPlugin([
    {
      from: 'node_modules/highlightjs/highlight.pack.min.js',
    },
    {
      from: 'assets/js/highlight.worker.js',
    },
    {
      from: 'node_modules/emojione/emoji_strategy.json',
    },
    {
      from: 'node_modules/datatables.net-plugins/i18n',
      to: 'datatables/i18n',
    },
    {
      from: 'node_modules/datatables.net-plugins/type-detection',
      to: 'datatables/type-detection',
    },
    {
      from: 'node_modules/datatables.net-plugins/sorting',
      to: 'datatables/sorting',
    },
  ]))
  .enableSassLoader()
  .enableVueLoader()
  .autoProvideVariables({
    '$': 'jquery',
    'jQuery': 'jquery',
    'window.$': 'jquery',
    'window.jQuery': 'jquery',
  })
  .enableSourceMaps(!Encore.isProduction())
;
// eslint-disable-next-line one-var
const config = Encore.getWebpackConfig();

// @see https://github.com/symfony/webpack-encore/issues/139#issuecomment-323585179
// Can be removed when stable and fixed.
config.plugins = config.plugins.filter(
  (plugin) => !(plugin instanceof webpack.optimize.UglifyJsPlugin)
);

config.resolve.alias = {
  handlebars: 'handlebars/dist/handlebars.min.js',
  styles: path.resolve(__dirname, './assets/css'),
  vue: 'vue/dist/vue.js',
};

if (Encore.isProduction()) {
  config.plugins.push(new UglifyJsPlugin());
  // @see https://github.com/vuejs/vue/issues/5063#issuecomment-301238826
  // @see https://stackoverflow.com/a/41627264/4487542
  // Since Vue 2.1.0 vue.js has been hardcoded as dev env and vue.commom.js as prod env
  config.resolve.alias = {
    vue: 'vue/dist/vue.common.js',
  };
} else {
  // @see https://github.com/symfony/webpack-encore/issues/236
  fs.writeFile('webpack.config.compiled.js', `module.exports = ${JSON.stringify(config)}`);
}

module.exports = config;

And I set the webpack.config.compiled.js file path to PHPStorm, but it still does not recognize this:

@import "~styles/variables";

Am I missing something?

picks44 commented 5 years ago

Hi,

Any update on this "issue"?

steven-pribilinskiy commented 5 years ago

I was hoping to find a solution here but had to came up with my own ) AFAIK the only thing that PhpStorm gets from webpack.config.js is the resolve.alias section

So I've simply created a webpack.config.aliases.js file with following content

/**
 * Aliases for require/import statements
 *
 * To have auto-completion and file navigation n PhpStorm point "webpack configuration file" setting
 * in "Languages & Frameworks > Javascript > Webpack" to this file
 */
const DIR_OPENBIZBOX = `${__dirname}/../src/Openbizbox`;

module.exports = {

    resolve: {
        alias: {
            '~backend': `${DIR_OPENBIZBOX}/BackendBundle/Resources`,
            '~designWizard': `${DIR_OPENBIZBOX}/DesignWizardBundle/Resources`,
            '~checkout': `${DIR_OPENBIZBOX}/CheckoutBundle/Resources`,
            '~frontend': `${DIR_OPENBIZBOX}/FrontendBundle/Resources`,
        }
    }
};

And then in webpack.config.js:

const config = Encore.getWebpackConfig();
const aliasesConfig = require('./webpack.config.aliases');

_.merge(config, aliasesConfig);

That's it ;)

Notice that I use ~ instead of @ as prefix, that's because PhpStorm is trying to find a package under @namespace

chiqui3d commented 5 years ago

Hi,

Any update?

Laruxo commented 5 years ago

Actually PHPStorm resolves JS files correctly (including dependencies). The problem is this: Error details: Encore.setOutputPath() cannot be called yet because the runtime environment doesn't appear to be configured. Make sure you're using the encore executable or call Encore.configureRuntimeEnvironment() first if you're purposely not calling Encore directly.

Vue cli has solution for this. They create additional webpack file that can be used without cli command. https://github.com/vuejs/vue-cli/blob/dev/packages/%40vue/cli-service/webpack.config.js

I currently solved this by creating webpack.ide.js file that has following line: Encore.configureRuntimeEnvironment('dev');

stof commented 5 years ago

suggestion: add a new method to be able to check whether the runtime environment was configured, allowing to do something like that:

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

if (!Encore.runtimeIsConfigured()) {
    Encore.configureRuntimeEnvironment(process.env.NODE_ENV || 'dev');
}

// Normal Encore usage here

This allows writing config files compatible with both the Encore CLI and the direct usage of the file. What do you think about that @weaverryan and @Lyrkan ?

stof commented 5 years ago

I quickly hacked that in my local setup, and I confirm that PHPStorm works with that. Here it what happened in the PHPStorm event log after doing the change:

Module resolution rules from webpack.config.js are now used for coding assistance.

stof commented 5 years ago

this means I can send a PR for that if we agree on the solution and on the naming

Lyrkan commented 5 years ago

@stof That's a really good idea, maybe isRuntimeConfigured() for the name? (since we already have things like isDev(), isProduction() and isDevServer())

Kocal commented 5 years ago

This can be closed no?

Lyrkan commented 5 years ago

Let's keep it open until we document how to do it properly using Encore.isRuntimeEnvironmentConfigured() and Encore.configureRuntimeEnvironment()

Kocal commented 5 years ago

Okay, I will check what I can do

javiereguiluz commented 5 years ago

The related Symfony Docs pull request has been merged: https://github.com/symfony/symfony-docs/pull/10947 thanks to the contribution made by @Kocal, so let's close this one as fixed. Thank you all!

Aerendir commented 5 years ago

Really really a great work!

Thank you @stof ! :)

Just as a side note, if you used the workaround in PHPStorm, to make this work you have to change the configuration of the IDE:

REMEMBER TO CHANGE IN PHPSTORM

Preferences > Languages & Framework > JavaScript > Webpack the path to the webpack.config.js file.

For me it was fakewebpack.config.js and I changed it back to webpack.config.js: now PHPStorm can interpret it correctly.

It required me some minutes to read again the discussion and find my old comment where I mentioned this change: so, maybe this side note could be useful for others!

Thank you again!

jav974 commented 5 years ago

Is it not simpler to include a jsconfig.json at the root of the project with content similar to : { "compilerOptions": { "target": "es2017", "allowSyntheticDefaultImports": false, "baseUrl": "./", "paths": { "alias1/*": ["path/to/src/*"], "alias2/*": ["other/*"], } }, "exclude": ["node_modules", "dist"] }

I configure my aliases this way since phpstorm analaysis doesn't perform well with Encore. It also works with vs code.

Kocal commented 5 years ago

I configure my aliases this way since phpstorm analaysis doesn't perform well with Encore.

That's weird because I have no issue with them. PHPStorm resolves aliases properly and can even use them when auto-importing a method/class...

Can you check https://symfony.com/doc/current/frontend/encore/faq.html#how-do-i-integrate-my-encore-configuration-with-my-ide ?

widoz commented 4 years ago

I had the same issue and solved with the @plfort workaround.

Would be really nice to have this works out of the box but not sure to understand if it's encore-webpack to add the fix or phpstorm. If phpstorm is there already an issue opened?

stof commented 4 years ago

@widoz the official solution (replacing the workaround of @plfort) is given in the Symfony documentation, which is linked in the comment of @Kocal just before yours.