Large Create-React-App Bundle Size - Optimized Production Build












5















Looking to deploy a create-react-app configuration on Heroku with the following buildpack: https://github.com/mars/create-react-app-buildpack



I've noticed I have a larger build size of 425 kb after being gZipped and my website is really slow on initial load



Are the following steps decent enough measures to reduce the bundle size? (ie. The best bang for buck precations). If not, what would else would you recommend? - I have not done this yet:




  1. Code Split where I can and use React Loadable (and maybe use
    react-universal-component)

  2. Ensure I load only the required modules (ie. import { map } from 'lodash/map';).




Other Solutions I'm reluctant to do




  • Use Preact as I don't want to break things :)


  • Two Quick Ways To Reduce React App’s Size In Production - It looks like this would require ejecting, and I'm curious if it's worth it?


Namely it adds the following:



new webpack.optimize.DedupePlugin(), //dedupe similar code
new webpack.optimize.UglifyJsPlugin(), //minify everything
new webpack.optimize.AggressiveMergingPlugin()//Merge chunks



Build time Gzip - Which I think is already done by create-react-app





My Source Map Explorer - Once again, will try and take down Firebase, remove Lottie, and import only necessary modules



I will ensure I remove some modules through specifying better...



Heroku Build Logs



-----> React.js (create-react-app) multi app detected
-----> Configure create-react-app build environment
Using `NODE_ENV=development`
=====> Downloading Buildpack: https://github.com/heroku/heroku-buildpack-multi.git
=====> Detected Framework: Multipack
=====> Downloading Buildpack: https://github.com/heroku/heroku-buildpack-nodejs.git
=====> Detected Framework: Node.js
-----> Creating runtime environment

NPM_CONFIG_LOGLEVEL=error
NPM_CONFIG_PRODUCTION=false
NODE_VERBOSE=false
NODE_ENV=production
NODE_MODULES_CACHE=true
-----> Installing binaries
engines.node (package.json): unspecified
engines.npm (package.json): unspecified (use default)

Resolving node version 8.x...
Downloading and installing node 8.11.1...
Using default npm version: 5.6.0
-----> Restoring cache
Loading 2 from cacheDirectories (default):
- node_modules
- bower_components (not cached - skipping)
-----> Building dependencies
Installing node modules (package.json + package-lock)
up to date in 14.708s
-----> Caching build
Clearing previous node cache
Saving 2 cacheDirectories (default):
- node_modules
- bower_components (nothing to cache)
-----> Pruning devDependencies
Skipping because NPM_CONFIG_PRODUCTION is 'false'
-----> Build succeeded!
=====> Downloading Buildpack: https://github.com/mars/create-react-app-inner-buildpack.git
=====> Detected Framework: React.js (create-react-app)
Using existing `static.json`
Enabling runtime environment variables
-----> Build succeeded!
=====> Downloading Buildpack: https://github.com/mars/create-react-app-inner-buildpack.git
=====> Detected Framework: React.js (create-react-app)
Using existing `static.json`
Enabling runtime environment variables
> journey-client@0.1.0 build /tmp/build_127125dc8ce0d7d71d8f78fe226cf544
> npm run build-css && react-scripts build
> journey-client@0.1.0 build-css /tmp/build_127125dc8ce0d7d71d8f78fe226cf544
> node-sass-chokidar src/ -o src/
Wrote 2 CSS files to /tmp/build_127125dc8ce0d7d71d8f78fe226cf544/src/
Creating an optimized production build...
File sizes after gzip:
495.27 KB build/static/js/main.b1129bd4.js
18.05 KB build/static/css/main.e2b6d04c.css
The project was built assuming it is hosted at the server root.
To override this, specify the homepage in your package.json.
For example, add this to build it for GitHub Pages:
"homepage" : "http://myname.github.io/myapp",
The build folder is ready to be deployed.
You may serve it with a static server:
npm install -g serve
serve -s build
=====> Downloading Buildpack: https://github.com/heroku/heroku-buildpack-static.git
=====> Detected Framework: Static HTML
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
-----> Installed directory to /app/bin
Using release configuration from last framework (Static HTML).
-----> Discovering process types
Procfile declares types -> (none)
Default types for buildpack -> web
-----> Compressing...
Done: 92.5M
-----> Launching...
Released v94









share|improve this question

























  • Any progress? I'm curious as well.

    – Mathieu K.
    Jun 7 '18 at 16:19











  • @MathieuK. Nothing yet. I think this is "normal". I think best practice is to be very judicious about which packages you include. Also look into code-splitting. I'm not sure how it works on the back end, but WebPack will automatically split your code into separate modules. If you can separate your large packages between the different React Classes which are split -> They will be loaded on the flow as required

    – njho
    Jun 8 '18 at 16:49
















5















Looking to deploy a create-react-app configuration on Heroku with the following buildpack: https://github.com/mars/create-react-app-buildpack



I've noticed I have a larger build size of 425 kb after being gZipped and my website is really slow on initial load



Are the following steps decent enough measures to reduce the bundle size? (ie. The best bang for buck precations). If not, what would else would you recommend? - I have not done this yet:




  1. Code Split where I can and use React Loadable (and maybe use
    react-universal-component)

  2. Ensure I load only the required modules (ie. import { map } from 'lodash/map';).




Other Solutions I'm reluctant to do




  • Use Preact as I don't want to break things :)


  • Two Quick Ways To Reduce React App’s Size In Production - It looks like this would require ejecting, and I'm curious if it's worth it?


Namely it adds the following:



new webpack.optimize.DedupePlugin(), //dedupe similar code
new webpack.optimize.UglifyJsPlugin(), //minify everything
new webpack.optimize.AggressiveMergingPlugin()//Merge chunks



Build time Gzip - Which I think is already done by create-react-app





My Source Map Explorer - Once again, will try and take down Firebase, remove Lottie, and import only necessary modules



I will ensure I remove some modules through specifying better...



Heroku Build Logs



-----> React.js (create-react-app) multi app detected
-----> Configure create-react-app build environment
Using `NODE_ENV=development`
=====> Downloading Buildpack: https://github.com/heroku/heroku-buildpack-multi.git
=====> Detected Framework: Multipack
=====> Downloading Buildpack: https://github.com/heroku/heroku-buildpack-nodejs.git
=====> Detected Framework: Node.js
-----> Creating runtime environment

NPM_CONFIG_LOGLEVEL=error
NPM_CONFIG_PRODUCTION=false
NODE_VERBOSE=false
NODE_ENV=production
NODE_MODULES_CACHE=true
-----> Installing binaries
engines.node (package.json): unspecified
engines.npm (package.json): unspecified (use default)

Resolving node version 8.x...
Downloading and installing node 8.11.1...
Using default npm version: 5.6.0
-----> Restoring cache
Loading 2 from cacheDirectories (default):
- node_modules
- bower_components (not cached - skipping)
-----> Building dependencies
Installing node modules (package.json + package-lock)
up to date in 14.708s
-----> Caching build
Clearing previous node cache
Saving 2 cacheDirectories (default):
- node_modules
- bower_components (nothing to cache)
-----> Pruning devDependencies
Skipping because NPM_CONFIG_PRODUCTION is 'false'
-----> Build succeeded!
=====> Downloading Buildpack: https://github.com/mars/create-react-app-inner-buildpack.git
=====> Detected Framework: React.js (create-react-app)
Using existing `static.json`
Enabling runtime environment variables
-----> Build succeeded!
=====> Downloading Buildpack: https://github.com/mars/create-react-app-inner-buildpack.git
=====> Detected Framework: React.js (create-react-app)
Using existing `static.json`
Enabling runtime environment variables
> journey-client@0.1.0 build /tmp/build_127125dc8ce0d7d71d8f78fe226cf544
> npm run build-css && react-scripts build
> journey-client@0.1.0 build-css /tmp/build_127125dc8ce0d7d71d8f78fe226cf544
> node-sass-chokidar src/ -o src/
Wrote 2 CSS files to /tmp/build_127125dc8ce0d7d71d8f78fe226cf544/src/
Creating an optimized production build...
File sizes after gzip:
495.27 KB build/static/js/main.b1129bd4.js
18.05 KB build/static/css/main.e2b6d04c.css
The project was built assuming it is hosted at the server root.
To override this, specify the homepage in your package.json.
For example, add this to build it for GitHub Pages:
"homepage" : "http://myname.github.io/myapp",
The build folder is ready to be deployed.
You may serve it with a static server:
npm install -g serve
serve -s build
=====> Downloading Buildpack: https://github.com/heroku/heroku-buildpack-static.git
=====> Detected Framework: Static HTML
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
-----> Installed directory to /app/bin
Using release configuration from last framework (Static HTML).
-----> Discovering process types
Procfile declares types -> (none)
Default types for buildpack -> web
-----> Compressing...
Done: 92.5M
-----> Launching...
Released v94









share|improve this question

























  • Any progress? I'm curious as well.

    – Mathieu K.
    Jun 7 '18 at 16:19











  • @MathieuK. Nothing yet. I think this is "normal". I think best practice is to be very judicious about which packages you include. Also look into code-splitting. I'm not sure how it works on the back end, but WebPack will automatically split your code into separate modules. If you can separate your large packages between the different React Classes which are split -> They will be loaded on the flow as required

    – njho
    Jun 8 '18 at 16:49














5












5








5


2






Looking to deploy a create-react-app configuration on Heroku with the following buildpack: https://github.com/mars/create-react-app-buildpack



I've noticed I have a larger build size of 425 kb after being gZipped and my website is really slow on initial load



Are the following steps decent enough measures to reduce the bundle size? (ie. The best bang for buck precations). If not, what would else would you recommend? - I have not done this yet:




  1. Code Split where I can and use React Loadable (and maybe use
    react-universal-component)

  2. Ensure I load only the required modules (ie. import { map } from 'lodash/map';).




Other Solutions I'm reluctant to do




  • Use Preact as I don't want to break things :)


  • Two Quick Ways To Reduce React App’s Size In Production - It looks like this would require ejecting, and I'm curious if it's worth it?


Namely it adds the following:



new webpack.optimize.DedupePlugin(), //dedupe similar code
new webpack.optimize.UglifyJsPlugin(), //minify everything
new webpack.optimize.AggressiveMergingPlugin()//Merge chunks



Build time Gzip - Which I think is already done by create-react-app





My Source Map Explorer - Once again, will try and take down Firebase, remove Lottie, and import only necessary modules



I will ensure I remove some modules through specifying better...



Heroku Build Logs



-----> React.js (create-react-app) multi app detected
-----> Configure create-react-app build environment
Using `NODE_ENV=development`
=====> Downloading Buildpack: https://github.com/heroku/heroku-buildpack-multi.git
=====> Detected Framework: Multipack
=====> Downloading Buildpack: https://github.com/heroku/heroku-buildpack-nodejs.git
=====> Detected Framework: Node.js
-----> Creating runtime environment

NPM_CONFIG_LOGLEVEL=error
NPM_CONFIG_PRODUCTION=false
NODE_VERBOSE=false
NODE_ENV=production
NODE_MODULES_CACHE=true
-----> Installing binaries
engines.node (package.json): unspecified
engines.npm (package.json): unspecified (use default)

Resolving node version 8.x...
Downloading and installing node 8.11.1...
Using default npm version: 5.6.0
-----> Restoring cache
Loading 2 from cacheDirectories (default):
- node_modules
- bower_components (not cached - skipping)
-----> Building dependencies
Installing node modules (package.json + package-lock)
up to date in 14.708s
-----> Caching build
Clearing previous node cache
Saving 2 cacheDirectories (default):
- node_modules
- bower_components (nothing to cache)
-----> Pruning devDependencies
Skipping because NPM_CONFIG_PRODUCTION is 'false'
-----> Build succeeded!
=====> Downloading Buildpack: https://github.com/mars/create-react-app-inner-buildpack.git
=====> Detected Framework: React.js (create-react-app)
Using existing `static.json`
Enabling runtime environment variables
-----> Build succeeded!
=====> Downloading Buildpack: https://github.com/mars/create-react-app-inner-buildpack.git
=====> Detected Framework: React.js (create-react-app)
Using existing `static.json`
Enabling runtime environment variables
> journey-client@0.1.0 build /tmp/build_127125dc8ce0d7d71d8f78fe226cf544
> npm run build-css && react-scripts build
> journey-client@0.1.0 build-css /tmp/build_127125dc8ce0d7d71d8f78fe226cf544
> node-sass-chokidar src/ -o src/
Wrote 2 CSS files to /tmp/build_127125dc8ce0d7d71d8f78fe226cf544/src/
Creating an optimized production build...
File sizes after gzip:
495.27 KB build/static/js/main.b1129bd4.js
18.05 KB build/static/css/main.e2b6d04c.css
The project was built assuming it is hosted at the server root.
To override this, specify the homepage in your package.json.
For example, add this to build it for GitHub Pages:
"homepage" : "http://myname.github.io/myapp",
The build folder is ready to be deployed.
You may serve it with a static server:
npm install -g serve
serve -s build
=====> Downloading Buildpack: https://github.com/heroku/heroku-buildpack-static.git
=====> Detected Framework: Static HTML
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
-----> Installed directory to /app/bin
Using release configuration from last framework (Static HTML).
-----> Discovering process types
Procfile declares types -> (none)
Default types for buildpack -> web
-----> Compressing...
Done: 92.5M
-----> Launching...
Released v94









share|improve this question
















Looking to deploy a create-react-app configuration on Heroku with the following buildpack: https://github.com/mars/create-react-app-buildpack



I've noticed I have a larger build size of 425 kb after being gZipped and my website is really slow on initial load



Are the following steps decent enough measures to reduce the bundle size? (ie. The best bang for buck precations). If not, what would else would you recommend? - I have not done this yet:




  1. Code Split where I can and use React Loadable (and maybe use
    react-universal-component)

  2. Ensure I load only the required modules (ie. import { map } from 'lodash/map';).




Other Solutions I'm reluctant to do




  • Use Preact as I don't want to break things :)


  • Two Quick Ways To Reduce React App’s Size In Production - It looks like this would require ejecting, and I'm curious if it's worth it?


Namely it adds the following:



new webpack.optimize.DedupePlugin(), //dedupe similar code
new webpack.optimize.UglifyJsPlugin(), //minify everything
new webpack.optimize.AggressiveMergingPlugin()//Merge chunks



Build time Gzip - Which I think is already done by create-react-app





My Source Map Explorer - Once again, will try and take down Firebase, remove Lottie, and import only necessary modules



I will ensure I remove some modules through specifying better...



Heroku Build Logs



-----> React.js (create-react-app) multi app detected
-----> Configure create-react-app build environment
Using `NODE_ENV=development`
=====> Downloading Buildpack: https://github.com/heroku/heroku-buildpack-multi.git
=====> Detected Framework: Multipack
=====> Downloading Buildpack: https://github.com/heroku/heroku-buildpack-nodejs.git
=====> Detected Framework: Node.js
-----> Creating runtime environment

NPM_CONFIG_LOGLEVEL=error
NPM_CONFIG_PRODUCTION=false
NODE_VERBOSE=false
NODE_ENV=production
NODE_MODULES_CACHE=true
-----> Installing binaries
engines.node (package.json): unspecified
engines.npm (package.json): unspecified (use default)

Resolving node version 8.x...
Downloading and installing node 8.11.1...
Using default npm version: 5.6.0
-----> Restoring cache
Loading 2 from cacheDirectories (default):
- node_modules
- bower_components (not cached - skipping)
-----> Building dependencies
Installing node modules (package.json + package-lock)
up to date in 14.708s
-----> Caching build
Clearing previous node cache
Saving 2 cacheDirectories (default):
- node_modules
- bower_components (nothing to cache)
-----> Pruning devDependencies
Skipping because NPM_CONFIG_PRODUCTION is 'false'
-----> Build succeeded!
=====> Downloading Buildpack: https://github.com/mars/create-react-app-inner-buildpack.git
=====> Detected Framework: React.js (create-react-app)
Using existing `static.json`
Enabling runtime environment variables
-----> Build succeeded!
=====> Downloading Buildpack: https://github.com/mars/create-react-app-inner-buildpack.git
=====> Detected Framework: React.js (create-react-app)
Using existing `static.json`
Enabling runtime environment variables
> journey-client@0.1.0 build /tmp/build_127125dc8ce0d7d71d8f78fe226cf544
> npm run build-css && react-scripts build
> journey-client@0.1.0 build-css /tmp/build_127125dc8ce0d7d71d8f78fe226cf544
> node-sass-chokidar src/ -o src/
Wrote 2 CSS files to /tmp/build_127125dc8ce0d7d71d8f78fe226cf544/src/
Creating an optimized production build...
File sizes after gzip:
495.27 KB build/static/js/main.b1129bd4.js
18.05 KB build/static/css/main.e2b6d04c.css
The project was built assuming it is hosted at the server root.
To override this, specify the homepage in your package.json.
For example, add this to build it for GitHub Pages:
"homepage" : "http://myname.github.io/myapp",
The build folder is ready to be deployed.
You may serve it with a static server:
npm install -g serve
serve -s build
=====> Downloading Buildpack: https://github.com/heroku/heroku-buildpack-static.git
=====> Detected Framework: Static HTML
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
-----> Installed directory to /app/bin
Using release configuration from last framework (Static HTML).
-----> Discovering process types
Procfile declares types -> (none)
Default types for buildpack -> web
-----> Compressing...
Done: 92.5M
-----> Launching...
Released v94






reactjs heroku webpack create-react-app






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited May 1 '18 at 3:51







njho

















asked May 1 '18 at 3:43









njhonjho

346316




346316













  • Any progress? I'm curious as well.

    – Mathieu K.
    Jun 7 '18 at 16:19











  • @MathieuK. Nothing yet. I think this is "normal". I think best practice is to be very judicious about which packages you include. Also look into code-splitting. I'm not sure how it works on the back end, but WebPack will automatically split your code into separate modules. If you can separate your large packages between the different React Classes which are split -> They will be loaded on the flow as required

    – njho
    Jun 8 '18 at 16:49



















  • Any progress? I'm curious as well.

    – Mathieu K.
    Jun 7 '18 at 16:19











  • @MathieuK. Nothing yet. I think this is "normal". I think best practice is to be very judicious about which packages you include. Also look into code-splitting. I'm not sure how it works on the back end, but WebPack will automatically split your code into separate modules. If you can separate your large packages between the different React Classes which are split -> They will be loaded on the flow as required

    – njho
    Jun 8 '18 at 16:49

















Any progress? I'm curious as well.

– Mathieu K.
Jun 7 '18 at 16:19





Any progress? I'm curious as well.

– Mathieu K.
Jun 7 '18 at 16:19













@MathieuK. Nothing yet. I think this is "normal". I think best practice is to be very judicious about which packages you include. Also look into code-splitting. I'm not sure how it works on the back end, but WebPack will automatically split your code into separate modules. If you can separate your large packages between the different React Classes which are split -> They will be loaded on the flow as required

– njho
Jun 8 '18 at 16:49





@MathieuK. Nothing yet. I think this is "normal". I think best practice is to be very judicious about which packages you include. Also look into code-splitting. I'm not sure how it works on the back end, but WebPack will automatically split your code into separate modules. If you can separate your large packages between the different React Classes which are split -> They will be loaded on the flow as required

– njho
Jun 8 '18 at 16:49












1 Answer
1






active

oldest

votes


















0
















  1. Only use packages that you are required to use. If you have packages of substantial size, only include the modules you require:



    import 'firebase/auth';
    import 'firebase/firestore';
    import isEqual from 'lodash.isequal';



  2. Use something like Gatsby.js which handles code splitting for you!


  3. Utilize practices like code splitting with next.js, react-loadable or other.


  4. Use a Server-Side Rendering Solution







share|improve this answer























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f50111079%2flarge-create-react-app-bundle-size-optimized-production-build%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    0
















    1. Only use packages that you are required to use. If you have packages of substantial size, only include the modules you require:



      import 'firebase/auth';
      import 'firebase/firestore';
      import isEqual from 'lodash.isequal';



    2. Use something like Gatsby.js which handles code splitting for you!


    3. Utilize practices like code splitting with next.js, react-loadable or other.


    4. Use a Server-Side Rendering Solution







    share|improve this answer




























      0
















      1. Only use packages that you are required to use. If you have packages of substantial size, only include the modules you require:



        import 'firebase/auth';
        import 'firebase/firestore';
        import isEqual from 'lodash.isequal';



      2. Use something like Gatsby.js which handles code splitting for you!


      3. Utilize practices like code splitting with next.js, react-loadable or other.


      4. Use a Server-Side Rendering Solution







      share|improve this answer


























        0












        0








        0









        1. Only use packages that you are required to use. If you have packages of substantial size, only include the modules you require:



          import 'firebase/auth';
          import 'firebase/firestore';
          import isEqual from 'lodash.isequal';



        2. Use something like Gatsby.js which handles code splitting for you!


        3. Utilize practices like code splitting with next.js, react-loadable or other.


        4. Use a Server-Side Rendering Solution







        share|improve this answer















        1. Only use packages that you are required to use. If you have packages of substantial size, only include the modules you require:



          import 'firebase/auth';
          import 'firebase/firestore';
          import isEqual from 'lodash.isequal';



        2. Use something like Gatsby.js which handles code splitting for you!


        3. Utilize practices like code splitting with next.js, react-loadable or other.


        4. Use a Server-Side Rendering Solution








        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 25 '18 at 20:36









        njhonjho

        346316




        346316
































            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f50111079%2flarge-create-react-app-bundle-size-optimized-production-build%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Costa Masnaga

            Fotorealismo

            Sidney Franklin