Closed wh1t3cAt1k closed 3 years ago
Perhaps some sort of configuration option to exclude a particular entry (i.e. polyfill) from processing altogether?
Hi, is it possible to post your full webpack config?
Also, can you try excluding @velixo/web-polyfill
instead?
Hi Michael.
I will try excluding and will post my full config tomorrow.
Just in case, what difference would it make if I use polyfills directly in the entry point(s) (I have two) as opposed to importing the polyfill package?
AFAIU the usage of URL will still be injected and executed before any code in my entry point gets a chance to execute, nope?
On Sun, Nov 8, 2020, 14:26 Michael Mok notifications@github.com wrote:
Hi, is it possible to post your full webpack config?
Also, can you try excluding @velixo/web-polyfill instead?
ā You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/pmmmwh/react-refresh-webpack-plugin/issues/246#issuecomment-723563949, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABHLV3VOGZWP4YPICUUSVNDSOZ57HANCNFSM4TJ5IRIQ .
@pmmmwh
Here is more of my webpack config:
By the way, the reason I used the @velixo/web-polyfill
package (it is an internal one) instead of importing the polyfills directly is because I reuse it for two web-based projects in a monorepo structure, and didn't want to repeat myself. However I still don't see how direct import would help?..
const configuration: Configuration & { devServer: unknown } = {
mode,
devtool: 'source-map',
entry: {
taskpane: path.resolve(sourceRoot, 'taskpane', 'index.tsx'),
'oauth-dialog': path.resolve(
sourceRoot,
'oauth-dialog',
'oauth-dialog.ts'
),
},
output: {
path: __dirname + '/wwwroot',
publicPath,
},
optimization: {
splitChunks: {
chunks: 'all',
},
runtimeChunk: 'single',
},
resolve: {
extensions: ['.ts', '.tsx', '.html', '.js'],
fallback: {
fs: require.resolve('browserify-fs'),
timers: require.resolve('timers-browserify'),
stream: require.resolve('stream-browserify'),
os: require.resolve('os-browserify/browser'),
process: require.resolve('process/browser'),
},
},
module: {
rules: [
{
test: /\.tsx?$/,
exclude: /node_modules/,
use: [
...(isHotLoadingEnabled
? [
{
loader: 'babel-loader',
options: {
plugins: [
require.resolve(
'react-refresh/babel'
),
],
},
},
]
: []),
{
loader: 'ts-loader',
options: {
configFile: 'tsconfig.build.json',
getCustomTransformers: (): unknown => ({
before: [tsNameof],
}),
},
},
],
},
{
test: /\.m?jsx?$/,
include: new RegExp(
'node_modules\\' +
path.sep +
'...several specific packages I need to downcompile to ES5 - don't want to process whole node_modules...'
),
use: {
loader: 'babel-loader',
options: {
presets: [
[
'@babel/preset-env',
{
targets: {
ie: '11',
},
},
],
],
},
},
},
{
test: /\.m?js/,
resolve: {
// work around a breaking change in webpack 5 that requires everyone to fully specify imports
fullySpecified: false,
},
},
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, 'css-loader'],
},
{
test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,
use: {
loader: 'file-loader',
options: {
name: 'assets/[name].[ext]',
},
},
},
],
},
plugins: [
new CleanWebpackPlugin({
cleanOnceBeforeBuildPatterns: isHotLoadingEnabled ? [] : ['**/*'],
}),
new CopyWebpackPlugin({
// @ts-ignore
patterns: [
{
to: 'taskpane.css',
from: path.resolve(sourceRoot, 'taskpane', 'taskpane.css'),
},
],
}),
new MiniCssExtractPlugin({
filename: isProductionMode ? '[name].css' : '[name].[hash].css',
chunkFilename: isProductionMode ? '[id].css' : '[id].[hash].css',
}),
new HtmlWebpackPlugin({
filename: 'taskpane.html',
template: path.resolve(sourceRoot, 'taskpane', 'taskpane.html'),
chunks: ['taskpane'],
}),
new HtmlWebpackPlugin({
filename: Constants.oauthDialogFilename,
template: path.resolve(
sourceRoot,
'oauth-dialog',
Constants.oauthDialogFilename
),
chunks: ['oauth-dialog'],
}),
new CopyWebpackPlugin({
// @ts-ignore
patterns: [
{
from: './assets',
to: 'assets',
globOptions: {
ignore: ['*.scss'],
},
},
],
}),
new EnvironmentPlugin(
EnvironmentConfiguration.getClientSideAvailableVariables()
),
...(shouldAnalyzeWebpackBundle
? [new BundleAnalyzerPlugin({ analyzerMode: 'static' })]
: []),
...(isHotLoadingEnabled
? [
new ReactRefreshWebpackPlugin({
forceEnable: true,
}),
]
: []),
],
target: ['web', 'es5'],
devServer: {
headers: {
'Access-Control-Allow-Origin': '*',
},
port: 5000,
https: false,
hot: isHotLoadingEnabled,
inline: isHotLoadingEnabled,
clientLogLevel: 'trace',
publicPath,
contentBase: outDir,
contentBasePublicPath: publicPath,
},
};
export default configuration;
Hi! I'll take a look at the webpack config and test things tomorrow.
However to answer some of your questions:
I will try excluding
Did that work for you?
AFAIK the usage of URL will still be injected and executed before any code in my entry point gets a chance to execute, nope?
In the plugin we do inject entries BEFORE your entries, so when the order is implicit (like how you would do it within an HTML which is out of Webpack's control) the detetion of order is not guaranteed. However I believe Webpack 5's Entry Descriptor feature does solve this problem by making the dependency explicit.
Just in case, what difference would it make if I use polyfills directly in the entry point(s) (I have two) as opposed to importing the polyfill package?
There is none.
An update to this - the next minor (major?) release of the plugin will contain an option to polyfill the URL
api (with core-js/features/url
) - we will ensure that all code dealing with URL
from the plugin will use the imported version instead.
I'm thinking to have it work a bit like a "ponyfill", where the functionality will only be patched within the scope of the plugin but not globally.
In case anyone wants to make this awesome plugin work with IE11 before the fix is ready, here's my solution. Assuming you are using HtmlWebpackPlugin
, put this into the <head>
element in your template:
<% if (webpackConfig.mode !== 'production') { %>
<!--
HACK: Until https://github.com/pmmmwh/react-refresh-webpack-plugin/issues/246 is resolved,
we need to polyfill window.URL manually outside of the webpack bundle, otherwise an error
is thrown in IE 11. Polyfilling via webpack is not an option, because all the entry points
get wrapped by the React Refresh plugin.
-->
<script src="https://polyfill.io/v3/polyfill.min.js?features=URL"></script>
<% } %>
Works just fine with webpack@5
and webpack-plugin-serve
. I couldn't get webpack-dev-server
to work with webpack@5
, because the 4-beta.0
version doesn't support IE11 due to https://github.com/webpack/webpack-dev-server/issues/2904 and related issues, and the latest stable version requires target: 'web'
(see https://github.com/webpack/webpack-dev-server/issues/2758) and target: ['es5', 'web']
(see webpackConfig.target docs) simultaneously to fix all the issues.
Fixed in #278 š
( cc @pmmmwh )
I am using this plugin (
0.4.3
latest version as of today) to support fast refresh in an IE11 environment, in conjunction withwebpack@5
andwebpack serve
(ex.webpack-dev-server
).I took all precaution to inject all the necessary polyfills by having a polyfill chunk in my
<head>
, which includes the polyfill forurl
.That's the source code of the chunk, it is of course compiled to ES5 by Babel.
It resides in a chunk called
evil-decrepit-browsers-polyfill
which, as I mentioned, is the first chunk injected into myindex.html
- nothing ever gets before it.The problem is that dev server in the
hot
mode (I use a combination ofinline
andhot
) injectsreact-refresh
runtime and helpers even to this chunk!And during the invocation of this injected code at the top I get an error in
getSocketUrlParts(resourceQuery)
:Object doesn't support this action
I confirm that the error happens because I haven't had a chance to polyfill this yet at the moment of code execution.
Using the below configuration doesn't help
This is a vicious cycle, the helpers seem to be injected into every file and I can't polyfill before the injected code executes.
Any thoughts?
If this is relevant, here are some other parts of my webpack configuration: