Skip to content

WJsjtu/comment-loader

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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-loaderbut before uglify which means the modules are already bundled together before the WebpackDefine plugin works.

This problem in this issue 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.

Releases

No releases published

Packages

No packages published