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

Razzle plugins + razzle-typescript-plugin #605

Merged
merged 10 commits into from
May 30, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion .all-contributorsrc
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,17 @@
"contributions": [
"example"
]
},
{
"login": "lucasterra",
"name": "Lucas Terra",
"avatar_url": "https://avatars2.githubusercontent.com/u/441058?v=4",
"profile": "https://www.linkedin.com/in/lucasterra7/",
"contributions": [
"code",
"example",
"plugin"
]
}
]
}
}
9 changes: 4 additions & 5 deletions examples/with-typescript/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,14 @@
"@types/express": "^4.11.1",
"@types/jest": "^22.2.3",
"@types/node": "9.6.6",
"@types/react": "^16.3.12",
"@types/react": "^16.3.13",
"@types/react-dom": "^16.0.5",
"@types/react-router-dom": "^4.2.6",
"@types/webpack-env": "^1.13.6",
"razzle": "^2.0.0-alpha.12",
"ts-jest": "^22.4.4",
"ts-loader": "^4.2.0",
"tslint": "^5.9.1",
"tslint-loader": "^4.2.0",
"razzle-plugin-typescript": "^2.0.0-alpha.12",
"ts-jest": "^22.4.5",
"tslint": "^5.10.0",
"tslint-react": "^3.5.1",
"typescript": "^2.8.3"
},
Expand Down
68 changes: 1 addition & 67 deletions examples/with-typescript/razzle.config.js
Original file line number Diff line number Diff line change
@@ -1,71 +1,5 @@
'use strict';

module.exports = {
modify(baseConfig, { target, dev }, webpack) {
const config = Object.assign({}, baseConfig);

config.resolve.extensions = config.resolve.extensions.concat([
'.ts',
'.tsx',
]);



// Locate eslint-loader and remove it (we're using tslint instead)
config.module.rules = config.module.rules.filter(
rule =>
!(
Array.isArray(rule.use) &&
rule.use.length > 0 &&
rule.use[0].options &&
'useEslintrc' in rule.use[0].options
)
);
// Add tslint-loader
config.module.rules.push({
include,
enforce: 'pre',
test: /\.tsx?$/,
loader: 'tslint-loader',
options: {
emitErrors: true,
configFile: './tslint.json',
},
});

// Safely locate Babel-Loader in Razzle's webpack internals
const babelLoader = config.module.rules.findIndex(
rule => rule.use[1].options && rule.use[1].options.babelrc
);

// Get the correct `include` option, since that hasn't changed.
// This tells Razzle which directories to transform.
const { include } = config.module.rules[babelLoader];

// Declare our TypeScript loader configuration
const tsLoader = {
include,
test: /\.tsx?$/,
loader: 'ts-loader',
options: {
transpileOnly: true,
},
};
// Add loader
config.module.rules.push(tsLoader)

// Additional options found at https://github.com/TypeStrong/ts-loader#faster-builds
// Add async typechecking errors
// config.plugins.push(new require('fork-ts-checker-webpack-plugin')())

// If you want to replace Babel with typescript to fully speed up build
// then do the following:
//
// - COMMENT out line 55
// - UNCOMMENT line 67
//
// config.module.rules[babelLoader] = tsLoader;

return config;
},
plugins: ['typescript'],
};
6 changes: 3 additions & 3 deletions examples/with-typescript/src/App.test.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import React from 'react';
import { render } from 'react-dom';

import App from './App';

Expand All @@ -8,7 +8,7 @@ import { MemoryRouter } from 'react-router-dom';
describe('<App />', () => {
test('renders without exploding', () => {
const div = document.createElement('div');
ReactDOM.render(
render(
<MemoryRouter>
<App />
</MemoryRouter>,
Expand Down
2 changes: 1 addition & 1 deletion examples/with-typescript/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as React from 'react';
Copy link
Owner

Choose a reason for hiding this comment

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

Put this back?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Why use import * as React when we have esModuleInterop?

Copy link
Owner

Choose a reason for hiding this comment

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

You right sorry. I got confused for a sec

import React from 'react';
import { Route, Switch } from 'react-router-dom';
import Home from './Home';

Expand Down
2 changes: 1 addition & 1 deletion examples/with-typescript/src/Home.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as React from 'react';
import React from 'react';
import logo from './react.svg';

import './Home.css';
Expand Down
6 changes: 3 additions & 3 deletions examples/with-typescript/src/client.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import React from 'react';
Copy link
Owner

Choose a reason for hiding this comment

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

Fix react imports

Copy link
Owner

Choose a reason for hiding this comment

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

ignore

import { hydrate } from 'react-dom';
import { BrowserRouter } from 'react-router-dom';

import App from './App';

ReactDOM.hydrate(
hydrate(
<BrowserRouter>
<App />
</BrowserRouter>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import express from 'express';
import app from './server';

if (module.hot) {
module.hot.accept('./server', function() {
module.hot.accept('./server', () => {
console.log('🔁 HMR Reloading `./server`...');
});
console.info('✅ Server-side HMR Enabled!');
Expand All @@ -11,8 +11,8 @@ if (module.hot) {
const port = process.env.PORT || 3000;

export default express()
.use((req, res) => app.handle(req, res))
.listen(port, function(err) {
.use(app)
.listen(port, (err: Error) => {
if (err) {
console.error(err);
return;
Expand Down
10 changes: 4 additions & 6 deletions examples/with-typescript/src/server.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as express from 'express';
import * as React from 'react';
import express from 'express';
Copy link
Owner

Choose a reason for hiding this comment

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

turn on esModuleInterop flag

import React from 'react';
import { renderToString } from 'react-dom/server';
import { StaticRouter } from 'react-router-dom';

Expand All @@ -8,13 +8,11 @@ import App from './App';
let assets: any;

const syncLoadAssets = () => {
assets = require(process.env.RAZZLE_ASSETS_MANIFEST!);
assets = require(process.env.RAZZLE_ASSETS_MANIFEST!);
};
syncLoadAssets();

const server = express();

server
const server = express()
.disable('x-powered-by')
.use(express.static(process.env.RAZZLE_PUBLIC_DIR!))
.get('/*', (req: express.Request, res: express.Response) => {
Expand Down
1 change: 1 addition & 0 deletions examples/with-typescript/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"noFallthroughCasesInSwitch": true,
"allowSyntheticDefaultImports": true,
"downlevelIteration": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"jsx": "react",
"lib": ["es6", "es2015", "es2017", "dom"],
Expand Down
1 change: 1 addition & 0 deletions lerna.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"packages/babel-preset-razzle",
"packages/create-razzle-app",
"packages/razzle-dev-utils",
"packages/razzle-plugin-*",
"examples/*"
],
"useWorkspaces": true,
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
"packages/babel-preset-razzle",
"packages/create-razzle-app",
"packages/razzle-dev-utils",
"packages/razzle-plugin-*",
"examples/*"
]
}
23 changes: 23 additions & 0 deletions packages/razzle-dev-utils/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,27 @@ try {
} catch (e) {
printErrors('Failed to compile.', [e]);
}
```

`makeLoaderFinder(loaderName: string): (rule: WebPackRule) => boolean;`

Helper function to find a loader in the webpack config object. Used for writing Razzle Plugins, or razzle modify functions.

Example:
```js
// razzle.config.js
const loaderFinder = require('razzle-dev-utils/makeLoaderFinder');

module.exports = {
modify(config) {
// Makes a finder function, to search for babel-loader
const babelLoaderFinder = makeLoaderFinder('babel-loader');

// Finds the JS rule containing babel-loader using our function
const jsRule = config.module.rules.find(babelLoaderFinder);

// Set cacheDirectory to true in our babel-loader
jsRule.use.find(babelLoaderFinder).options.cacheDirectory = true;
}
}
```
22 changes: 22 additions & 0 deletions packages/razzle-dev-utils/makeLoaderFinder.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
'use strict';

const makeLoaderFinder = loaderName => rule => {
// i.e.: /eslint-loader/
const loaderRegex = new RegExp(`[/\\\\]${loaderName}[/\\\\]`);

// Checks if there's a loader string in rule.loader matching loaderRegex.
const inLoaderString =
typeof rule.loader === 'string' && rule.loader.match(loaderRegex);

// Checks if there is an object inside rule.use with loader matching loaderRegex, OR
const inUseArray =
Array.isArray(rule.use) &&
rule.use.find(
loader =>
typeof loader.loader === 'string' && loader.loader.match(loaderRegex)
);

return inUseArray || inLoaderString;
};

module.exports = makeLoaderFinder;
3 changes: 2 additions & 1 deletion packages/razzle-dev-utils/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
"printErrors.js",
"FriendlyErrorsPlugin.js",
"webpackHotDevClient.js",
"setPorts.js"
"setPorts.js",
"makeLoaderFinder.js"
],
"dependencies": {
"chalk": "1.1.3",
Expand Down
6 changes: 6 additions & 0 deletions packages/razzle-plugin-typescript/.eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"env": {
"jest": true,
"node": true
}
}
Copy link
Owner

Choose a reason for hiding this comment

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

I think we should actually move eslint out of here. I think we ought to move it of the core as well, making a razzle-plugin-eslint.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh, this was just to make linting work on the code and test files. It won't be used by plugin users.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

But yeah. I agree with removing eslint from the default webpack config.

Copy link
Owner

Choose a reason for hiding this comment

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

Ahh sorry I just looked at the filename

62 changes: 62 additions & 0 deletions packages/razzle-plugin-typescript/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# razzle-plugin-typescript

This package contains a plugin for using TypeScript with Razzle

## Usage in Razzle Projects

```
yarn add razzle-plugin-typescript
```

Using the plugin with the default options

```js
// razzle.config.js

module.exports = {
plugins: [
'typescript'
],
};
```

### With custom options:

```js
// razzle.config.js

module.exports = {
plugins: [
{
name: 'typescript',
options: {
useBabel: false,
tsLoader: {
transpileOnly: true,
experimentalWatchApi: true,
},
forkTsChecker: {
tsconfig: './tsconfig.json',
tslint: './tslint.json',
watch: './src',
typeCheck: true,
}
},
},
],
};
```

## Options

__useBabel: _boolean___ (defaults: false)

Set `useBabel` to `true` if you want to keep using `babel` for _JS_/_TS_ interoperability, or if you want to apply any babel transforms to typescript files. (i.e.: [`babel-plugin-styled-components`](https://github.com/styled-components/babel-plugin-styled-components)).

__tsLoader: _TSLoaderOptions___ (defaults: { transpileOnly: true, experimentalWatchApi: true })

Use this to override [`ts-loader`](https://github.com/TypeStrong/ts-loader) options. Check all the options here: [ts-loader options](https://github.com/TypeStrong/ts-loader#loader-options).

__forkTsChecker: _TSCheckerOptions___ (defaults: { tsconfig: './tsconfig.json', tslint: './tslint.json', watch: './src', typeCheck: true })

Use this to override [`fork-ts-checker-webpack-plugin`](https://github.com/Realytics/fork-ts-checker-webpack-plugin) options. Check all the options here: [fork-ts-checker-webpack-plugin options](https://github.com/Realytics/fork-ts-checker-webpack-plugin#options).
12 changes: 12 additions & 0 deletions packages/razzle-plugin-typescript/helpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
'use strict';
const makeLoaderFinder = require('razzle-dev-utils/makeLoaderFinder');

const babelLoaderFinder = makeLoaderFinder('babel-loader');
const tsLoaderFinder = makeLoaderFinder('ts-loader');
const eslintLoaderFinder = makeLoaderFinder('eslint-loader');

module.exports = {
eslintLoaderFinder,
babelLoaderFinder,
tsLoaderFinder,
};
Loading