Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixing Windows Support #28

Merged
merged 5 commits into from
Jun 21, 2017
Merged

Conversation

weaverryan
Copy link
Member

@weaverryan weaverryan commented Jun 16, 2017

In a few places, we rely (relied) on doing some "string replace" on paths. Obviously, that doesn't play well with the windows \ directory separators. This fixes the few places that rely on this and includes tests that exposed those failures on AppVeyor.

@weaverryan weaverryan force-pushed the windows-paths-fix branch 2 times, most recently from 645607c to d84ef11 Compare June 16, 2017 17:38
// start with outputPath, then join publicPath with it, see if it equals outputPath
// in loop, do dirname on outputPath and repeat
// eventually, you (may) get to the right path
var contentBase = outputPath;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be let rather than var

@weaverryan weaverryan changed the title [WIP] Fixing Windows Support Fixing Windows Support Jun 20, 2017
@weaverryan
Copy link
Member Author

Tests are green 🎆 - this is ready :)

* We use the intersection of the publicPath (or manifestKeyPrefix) and outputPath
* to determine the "document root" of the web server. For example:
* * outputPath = /var/www/public/build
* * publicPath = /build/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what if publicPath is /subdir/build/ ? AFAIK path.join(contentBase, publicPath) === outputPath will never be true, as outputPath will use \ everywhere, while path.join(contentBase, publicPath) will have some /

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're correct. But, if the user has a publicPath that is not a sub-string of the outputPath, they will already have received an error forcing them to set manifestKeyPrefix (you do not need to set this manually... until you deploy under a subdirectory or set publicPath to a CDN). So, this situation won't happen. I've just pushed a commit to hopefully clarify this - it's a bit complex since different parts of the system are working together. It is possible that the user will set a manifestKeyPrefix that is not a substring of the outputPath, and then they would see this error (because this is not allowed)


let outputPath = webpackConfig.outputPath;
// for comparison purposes, change \ to / on Windows
outputPath = outputPath.split('\\').join('/');
Copy link
Member

@stof stof Jun 21, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is split+join faster than .replace(/\\/g, '/') ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

replace only replaces the first occurrence :/

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no, when using a regex, it depends whether you pass a regex matching the first place or all of them (think preg_match vs preg_match_all in PHP). I added the g modifier on my regex.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right! I was mixing this up with the non-regex behavior or replace, which only replaces the first. I'll update these to regex (it's less "weird" than this)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still suggest doing a benchmark (especially before contributing to webpack-manifest-plugin

if (process.platform === 'win32') {
moduleAssets[file] = moduleAssets[file].split('\\').join('/');
}
/* *** MODIFICATION END *** */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be contributed upstream too ?

*
* @returns {boolean}
*/
function isWindows() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this could be a const rather than a function, as the value being returned will always be the same:

const isWindows = process.platform === 'win32'

// ...

        if (isWindows) {
            this.skip();
        }

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

});

describe('generateManifestKeyPrefix', () => {
it('manifestKeyPrefix is correctly not required on windows', () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't this be skipped on Unix ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally, the code for parsing these paths would be really portable and work on any OS (e.g. even on UNIX, it handles the Windows paths correctly). So far, I've only skipped tests when this is not true - i.e. when Windows does not handle Unix correctly or Unix does not handle Windows correctly.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, based on your other suggestion - I've removed all of the skips and just add a bit of isWindows logic in each function to change the paths based on OS. This means all tests will run on both OS's - best of both worlds (and less duplication as you mentioned)

expect(actualPrefix).to.equal('build/');
});

it('with absolute publicPath, manifestKeyPrefix must be set', () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't this be skipped on windows ?


it('when outputPath and publicPath are incompatible, manifestKeyPrefix must be set', () => {
const config = createConfig();
config.outputPath = '/tmp/public/build';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to have a windows test for that too (or just change the output path here depending on the OS instead of duplicating everything)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea to alternate the path based on OS - doing that!

* Some tests are very specific to different operating systems.
* We use this to only run them when needed.
*
* @returns {boolean}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@returns is wrong for a constant

// for Windows, we want the keys to use /, not \
// (and path.join will obviously use \ in Windows)
if (process.platform === 'win32') {
moduleAssets[file] = moduleAssets[file].replace(/\\/g).join('/');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is broken. proper code is .replace(/\\/g, '/')

* Refactoring delicate path logic into path-util

* Fixing logic that relied in unix-style paths

* Fixed a bug inside webpack-manifest-plugin that used \ for manifest.json key paths on Windows
@weaverryan weaverryan merged commit 78a0680 into symfony:master Jun 21, 2017
weaverryan added a commit that referenced this pull request Jun 21, 2017
This PR was squashed before being merged into the master branch (closes #28).

Discussion
----------

Fixing Windows Support

In a few places, we rely (relied) on doing some "string replace" on paths. Obviously, that doesn't play well with the windows `\` directory separators. This fixes the few places that rely on this and includes tests that exposed those failures on AppVeyor.

Commits
-------

78a0680 cs
6164d80 Tweaks thanks to Stof, including combining Unix & windows tests
162d5f5 Moving some validation logic to be more clear about the flow
5f8ff97 Fixing a small bug when reporting the relative output path
6c65840 Fixing Windows support:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants