-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: webpack resolutions for #882, add webpack example
- Loading branch information
Showing
13 changed files
with
2,246 additions
and
75 deletions.
There are no files selected for viewing
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
module.exports = { | ||
sourceMaps: true, | ||
presets: [ | ||
[ | ||
require.resolve('@babel/preset-env'), | ||
{ | ||
targets: 'latest 2 versions', | ||
modules: false, | ||
}, | ||
], | ||
require.resolve('@babel/preset-react'), | ||
], | ||
plugins: [ | ||
require.resolve('@babel/plugin-syntax-dynamic-import'), | ||
require.resolve('@babel/plugin-proposal-class-properties'), | ||
], | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
{ | ||
"name": "graphiql-example-webpack", | ||
"version": "0.0.4", | ||
"private": true, | ||
"license": "MIT", | ||
"description": "A GraphiQL example with webpack and typescript", | ||
"scripts": { | ||
"build-demo": "webpack", | ||
"start": "webpack-dev-server --watch" | ||
}, | ||
"dependencies": { | ||
"express": "^4.17.1", | ||
"express-graphql": "^0.9.0", | ||
"graphiql": "file:../../graphiql", | ||
"graphql": "14.5.6", | ||
"react": "16.10.2" | ||
}, | ||
"devDependencies": { | ||
"babel-loader": "^8.0.6", | ||
"html-webpack-plugin": "^3.2.0", | ||
"react-dom": "^16.11.0", | ||
"style-loader": "^1.0.0", | ||
"css-loader": "3.2.0", | ||
"webpack": "^4.41.0", | ||
"webpack-cli": "^3.3.9", | ||
"webpack-dev-server": "^3.9.0", | ||
"@babel/plugin-syntax-dynamic-import": "7.2.0", | ||
"@babel/plugin-proposal-class-properties": "7.7.0", | ||
"@babel/preset-react": "7.7.0", | ||
"@babel/preset-env": "7.7.1" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
<!DOCTYPE html> | ||
<html lang="en" dir="ltr"> | ||
<head> | ||
<meta charset="UTF-8" /> | ||
<meta | ||
name="viewport" | ||
content="width=device-width, initial-scale=1, shrink-to-fit=no" | ||
/> | ||
<title>GraphiQL Webpack Example!</title> | ||
</head> | ||
|
||
<body> | ||
<style> | ||
body { | ||
padding: 0; | ||
margin: 0; | ||
min-height: 100vh; | ||
} | ||
#root { | ||
height: 100vh; | ||
} | ||
</style> | ||
<div id="root"></div> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import React from 'react'; | ||
import { render } from 'react-dom'; | ||
import GraphiQL from 'graphiql'; | ||
import 'graphiql/graphiql.css'; | ||
|
||
const App = () => ( | ||
<GraphiQL | ||
style={{ height: '100vh' }} | ||
fetcher={async graphQLParams => { | ||
const data = await fetch('https://swapi.graph.cool', { | ||
method: 'POST', | ||
headers: { | ||
Accept: 'application/json', | ||
'Content-Type': 'application/json', | ||
}, | ||
body: JSON.stringify(graphQLParams), | ||
credentials: 'include', | ||
}); | ||
return data.json(); | ||
}} | ||
/> | ||
); | ||
|
||
render(<App />, document.getElementById('root')); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
const HtmlWebpackPlugin = require('html-webpack-plugin'); | ||
const path = require('path'); | ||
const isDev = process.env.NODE_ENV === 'development'; | ||
|
||
module.exports = { | ||
entry: isDev | ||
? [ | ||
'react-hot-loader/patch', // activate HMR for React | ||
'webpack-dev-server/client?http://localhost:8080', // bundle the client for webpack-dev-server and connect to the provided endpoint | ||
'webpack/hot/only-dev-server', // bundle the client for hot reloading, only- means to only hot reload for successful updates | ||
'./index.jsx', // the entry point of our app | ||
] | ||
: './index.jsx', | ||
context: path.resolve(__dirname, './src'), | ||
mode: 'development', | ||
devtool: 'inline-source-map', | ||
performance: { | ||
hints: false, | ||
}, | ||
module: { | ||
rules: [ | ||
{ | ||
test: /\.html$/, | ||
use: ['file?name=[name].[ext]'], | ||
}, | ||
// for graphql module, which uses mjs still | ||
{ | ||
type: 'javascript/auto', | ||
test: /\.mjs$/, | ||
use: [], | ||
include: /node_modules/, | ||
}, | ||
{ | ||
test: /\.(js|jsx)$/, | ||
use: [ | ||
{ | ||
loader: 'babel-loader', | ||
options: { | ||
presets: [ | ||
['@babel/preset-env', { modules: false }], | ||
'@babel/preset-react', | ||
], | ||
}, | ||
}, | ||
], | ||
}, | ||
{ | ||
test: /\.css$/, | ||
use: ['style-loader', 'css-loader'], | ||
}, | ||
{ | ||
test: /\.svg$/, | ||
use: [{ loader: 'svg-inline-loader' }], | ||
}, | ||
], | ||
}, | ||
resolve: { | ||
extensions: ['.js', '.json', '.jsx', '.css', '.mjs'], | ||
}, | ||
plugins: [new HtmlWebpackPlugin({ template: 'index.html.ejs' })], | ||
devServer: { | ||
hot: true, | ||
// bypass simple localhost CORS restrictions by setting | ||
// these to 127.0.0.1 in /etc/hosts | ||
allowedHosts: ['local.test.com', 'graphiql.com'], | ||
}, | ||
node: { | ||
fs: 'empty', | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"printWidth": 120 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
import path from 'path'; | ||
|
||
import { | ||
getFileExtension, | ||
getPathWithoutExtension, | ||
resolveFile, | ||
requireFile, | ||
} from './file'; | ||
|
||
describe('getFileExtension', () => { | ||
it('should resolve an extension', () => { | ||
const extension = getFileExtension('example/example.txt'); | ||
expect(extension).toEqual('txt'); | ||
}); | ||
it('should resolve null when no extension is present', () => { | ||
const extension = getFileExtension('example/example'); | ||
expect(extension).toEqual(null); | ||
}); | ||
|
||
it('should return an extension with multiple dots in the path', () => { | ||
const extension = getFileExtension( | ||
'example.example/example/something.esm.js', | ||
); | ||
expect(extension).toEqual('js'); | ||
}); | ||
}); | ||
|
||
describe('getPathWithoutExtension', () => { | ||
it('should resolve when path has extension', () => { | ||
const extension = getPathWithoutExtension('example/example.txt', 'txt'); | ||
expect(extension).toEqual('example/example'); | ||
}); | ||
it('should resolve when path has no extension', () => { | ||
const extension = getPathWithoutExtension( | ||
'example/example.example/example', | ||
null, | ||
); | ||
expect(extension).toEqual('example/example.example/example'); | ||
}); | ||
}); | ||
|
||
describe('requireFile', () => { | ||
it('should require file with extension', async () => { | ||
const file = await requireFile('../package.json'); | ||
expect(file.name).toEqual('graphql-language-service-interface'); | ||
}); | ||
it('should fail when requiring an invalid extension', () => { | ||
expect(() => requireFile('../.npmignore')).toThrowError( | ||
`cannot require() module with extension 'npmignore'`, | ||
); | ||
}); | ||
it('should require file with no extension using js', async () => { | ||
const config = await requireFile(path.join(__dirname, '../../../jest.config')); | ||
await expect(config.collectCoverage).toEqual(true); | ||
}); | ||
it('should require file with no extension using json', async () => { | ||
const file = await requireFile(path.join(__dirname, '../package')); | ||
expect(file.name).toEqual('graphql-language-service-interface'); | ||
}); | ||
}); | ||
|
||
describe('resolveFile', () => { | ||
it('should resolve when path has extension', () => { | ||
const resolvedPath = resolveFile('../package.json'); | ||
expect(resolvedPath).toEqual( | ||
require.resolve(path.join(__dirname, '../package.json')), | ||
); | ||
}); | ||
|
||
it('should resolve when path has extension', () => { | ||
const resolvedPath = resolveFile(path.join(__dirname, '../package')); | ||
expect(resolvedPath).toEqual( | ||
require.resolve(path.join(__dirname, '../package.json')), | ||
); | ||
}); | ||
it('should resolve when path has extension', () => { | ||
const resolvedPath = resolveFile('../../../.eslintrc.js'); | ||
expect(resolvedPath).toEqual( | ||
require.resolve(path.join(__dirname, '../../../.eslintrc.js')), | ||
); | ||
}); | ||
it('should resolve when path has no extension', () => { | ||
const resolvedPath = resolveFile( | ||
path.join(__dirname, '../../../.eslintrc'), | ||
); | ||
expect(resolvedPath).toEqual( | ||
require.resolve(path.join(__dirname, '../../../.eslintrc.js')), | ||
); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import fs from 'fs'; | ||
|
||
export function getFileExtension(filePath: string): string | null { | ||
const pathParts = /^.+\.([^.]+)$/.exec(filePath); | ||
// if there's a file extension | ||
if (pathParts && pathParts.length > 1) { | ||
return pathParts[1]; | ||
} | ||
return null; | ||
} | ||
|
||
export function getPathWithoutExtension( | ||
filePath: string, | ||
extension: string | null, | ||
) { | ||
let pathWithoutExtension = filePath; | ||
if (extension) { | ||
pathWithoutExtension = filePath.substr( | ||
0, | ||
filePath.length - (extension.length + 1), | ||
); | ||
} | ||
return pathWithoutExtension; | ||
} | ||
|
||
// these make webpack happy | ||
|
||
export function resolveFile(filePath: string) { | ||
const extension = getFileExtension(filePath); | ||
const pathWithoutExtension = getPathWithoutExtension(filePath, extension); | ||
switch (extension) { | ||
case 'js': { | ||
return require.resolve(pathWithoutExtension + '.js'); | ||
} | ||
case 'json': { | ||
return require.resolve(pathWithoutExtension + '.json'); | ||
} | ||
default: { | ||
if (fs.existsSync(filePath + `.js`)) { | ||
return require.resolve(filePath + '.js'); | ||
} | ||
if (fs.existsSync(filePath + `.json`)) { | ||
return require.resolve(filePath + '.json'); | ||
} | ||
if (extension) { | ||
throw Error( | ||
`cannot require.resolve() module with extension '${extension}'`, | ||
); | ||
} | ||
} | ||
} | ||
} | ||
|
||
// again, explicit with the extensions | ||
// dynamic imports, aka import(packageName).then() | ||
// is available in node 9.7+, and most modern browsers | ||
|
||
export function requireFile(filePath: string) { | ||
const extension = getFileExtension(filePath); | ||
const pathWithoutExtension = getPathWithoutExtension(filePath, extension); | ||
switch (extension) { | ||
case 'js': { | ||
return import(pathWithoutExtension + '.js'); | ||
} | ||
case 'json': { | ||
return import(pathWithoutExtension + '.json'); | ||
} | ||
default: { | ||
if (fs.existsSync(filePath + `.js`)) { | ||
return import(filePath + '.js'); | ||
} | ||
if (fs.existsSync(filePath + `.json`)) { | ||
return import(filePath + '.json'); | ||
} | ||
if (extension) { | ||
throw Error(`cannot require() module with extension '${extension}'`); | ||
} | ||
throw Error(`No extension found, and no supported file found to match '${filePath}'`); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.