An open API service indexing awesome lists of open source software.

https://github.com/wjsjtu/comment-loader


https://github.com/wjsjtu/comment-loader

comment loader macros precompiling tree-shaking wepback

Last synced: about 2 months ago
JSON representation

Awesome Lists containing this project

README

          

# comment-loader
A wepback loader using comment to do precompilation work.

###Install
`npm install --save-dev comment-loader`

###Why we need it?
Conditional code is not allowed in ES6+, this means you cannot use `if-else` or `switch-case` structure to enable/disable some modules.
However if some precompilation work can be performed before webpack pass your code to babel or other ES transformers, the problem can be solved easily.
Macro like C-style macro can be a way to do all this.

###What different?
Some Macro loaders can already be found on github or npm. However, they usually cause some side-effects. Using Macro directly will break the syntax which will cause big problem if the loader is not available.

Here I use the hack on comments and `babylon` parser to detect the define Macro. Using comments is a way to lower the side-effects as many as possible, though it still bother IDE sometimes.
Comments are not force to be at the beginning of the line, since `babylon` can always detect AST correctly. Another important reason why I use `babylon` is that I hope the comments can do more in future. Maybe I'll let loader support simple `if-else` or `switch-case` structures in comments with some defined patterns.

###When to use it?
Here is an example of developing app with redux.

```
import {createStore, compose} from 'redux';
import rootReducer from '../reducers';
import {persistState} from 'redux-devtools';
import DevTools from '../containers/DevTools';

const enhancer = compose(
DevTools.instrument(),
persistState(
window.location.href.match(
/[?&]debug_session=([^]+)\b/
)
)
);

export default function configureStore(initialState) {

return createStore(rootReducer, initialState, process.env.NODE_ENV === 'production' ? undefined : enhancer);

}
```
`redux-devtools` is very useful when developing apps, however it only use `WebpackDefine` plugin can have great problem when build bundles.`WebpackDefine` works after `babel-loader`but before `uglify` which means the modules are already bundled together before the `WebpackDefine` plugin works.

This problem in this [issue](https://github.com/webpack/webpack/issues/2061) is almost the same. The tree shaking won't work because building modules is performed before removing dead code. Webpack can mark unused imports/exports, maybe this is also possible for the issue by some ways like simply marking the statements and specifiers. But in my case, I think it is impossible. If an analyzer can tell `enhancer` is no longer used when `process.env.NODE_ENV === 'production'`, and it cannot tell whether `compose` use it or not.
If recursive detection can be performed, it must be a time consuming work.

I now think these kind of use `WebpackDefine` plugin is a mistake, especially when the variables defined are related to the module dependency. So I don't think `Webpack` should focus on this kind of problem.

This loader allows you to write code like below:
```
import {createStore, compose} from 'redux';
import rootReducer from '../reducers';

//<#IF_DEF DEBUG>
import {persistState} from 'redux-devtools';
import DevTools from '../containers/DevTools';

const enhancer = compose(
DevTools.instrument(),
persistState(
window.location.href.match(
/[?&]debug_session=([^]+)\b/
)
)
);

//<#END_IF>

export default function configureStore(initialState) {

let store;

//<#IF_DEF DEBUG>

store = createStore(rootReducer, initialState, enhancer);

//<#ELSE>

store = createStore(rootReducer, initialState);

//<#END_IF>
return store;

}
```
The `<#IF_DEF DEBUG>` , `<#ELSE>` and `<#END_IF>` are all needed.

###How to use?
Webpack config file.

```
module: {
rules: [
{
test: /\.js$/,
include: [
path.resolve(__dirname, '../src')
],
exclude: [
path.resolve(__dirname, '../node_modules')
],
use: [
{
loader: 'babel-loader'
},
{
loader: 'comment-loader',
options: {
definition: ['DEBUG']//['RELEASE']
}
},
]
}
]
}
```
>Note: You should always put `comment-loader` on the right of `babel-loader` or other loaders.
>`babel-loader` will mess up the comments between `import` lines thus making macros invalid.