Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
306 views
in Technique[技术] by (71.8m points)

coffeescript - How can I setup webpack to minify and combine scss and javascript like CodeKit?

I'm having trouble using webpack instead of Codekit v1.9.3. I started working to move from CodeKit to Grunt and Gulp, and then learned about webpack which sounds very cool. I just can't seem to get it working correctly.

"Like Codekit" means I can:

  • Write javascript with the coffeescript syntax
  • Have all script source files and libraries minified / uglified and combined into one file
  • Selectively include components of the bootstrap-sass (scss) framework as needed
  • Maintain a small file with bootstrap customizations via sass variables, like $brand-primary
  • Use webpack --watch to compile both scripts and styles automatically when they are changed
  • End up with one css file and one script file that can be included with a stylesheet and script tag.

Codekit Project Setup

Bower resources:

I'm currently storing these globally, outside of the project:

~/bower_components/twbs-bootstrap-sass/vendor/assets/stylesheets

Because CodeKit supports compass, I've got this in my config.rb file:

add_import_path "~/bower_components/twbs-bootstrap-sass/vendor/assets/stylesheets"

Project Structure

js/fancybox.js
js/main.js               <-- currently the compiled js 'output' file
js/main.coffee

css/styles.css           <-- currently the compiled css 'output' file

scss/styles.scss
scss/modules/_bootstrap-customizations.scss
scss/modules/_typography.scss
scss/partials/_header.scss
scss/partials/_footer.scss

Contents of styles.scss

@import "modules/bootstrap-customizations";  # local customizations
@import "bootstrap/variables";
@import "bootstrap/mixins";
...                                          # load bootstrap files as required
@import "bootstrap/wells";

System Setup:

  • system: OS X 10.9
  • node - v0.10.32
  • npm - v2.1.7
  • zsh - zsh 5.0.7 (x86_64-apple-darwin13.4.0)

node was installed with homebrew's brew install node and seems to be working fine otherwise.


What I've Tried

I've read over these pages:

I've attempted to create a webpack.config.js file several times, my latest attempt was several versions of this:

module.exports = {
    entry: [
    "./node_modules/bootstrap-sass-webpack!./bootstrap-sass.config.js",
    "./js/main.coffee"
    ],
    output: {
        path: __dirname,
        filename: "main.js"
    },
    module: {
        loaders: [
        { test: /.css$/, loader: "style!css" }
        ]
    }
};

Webpack Error

When I run webpack I get this:

ERROR in ./~/bootstrap-sass-webpack/~/css-loader!/Users/cwd/~/sass-loader!./~/bootstrap-sass-webpack/bootstrap-sass-styles.loader.js!./bootstrap-sass.config.js
stdin:1: file to import not found or unreadable: "~bootstrap-sass/assets/stylesheets/bootstrap/variables

NPM Error

I get an error when attempting to npm install bootstrap-sass, and not had any luck when searching for a solution. I'm not even sure I need this module.

npm ERR! Darwin 13.4.0
npm ERR! argv "node" "/usr/local/bin/npm" "install" "bootstrap-sass"
npm ERR! node v0.10.32
npm ERR! npm  v2.1.7
npm ERR! code EPEERINVALID

npm ERR! peerinvalid The package bootstrap-sass does not satisfy its siblings' peerDependencies requirements!
npm ERR! peerinvalid Peer bootstrap-sass-webpack@0.0.3 wants bootstrap-sass@~3.2.0

npm ERR! Please include the following file with any support request:
npm ERR!     /Users/cwd/webpack-test/npm-debug.log

Sources of Confusion

The most confusing parts of webpack for me are:

  1. Where should things like require("bootstrap-sass-webpack") be added - is it in the webpack.config.js file, or in the js/main.js file?
  2. Should modules like this available to webpack as soon as they are installed with npm install ?
  3. I thought that I should do npm install webpack -g so that webpack was installed globally, and use npm install without the -g for the other modules. However, I don't see any node_modules folder being created in my project. Shouldn't there be one?
  4. How are the search paths determined / specified for things like require("bootstrap-sass-webpack") ?

What node modules should I install to be able to do this? And what should my webpack.config.js look like?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Introduction

Webpack is mainly a JavaScript-bundler. Its "native" language is JavaScript and every other source requires a loader which transforms it to JavaScript. If you require() an html-file for example...

var template = require("./some-template.html");

...you'll need the html-loader. It turns...

<div>
    <img src="./assets/img.png">
</div>

...into...

module.exports = "<div>
    <img src="" + require("./assets/img.png") + "">
</div>";

If a loader doesn't return JavaScript, it needs to be "piped" to another loader.


How to load SASS-files

Configure loaders

In order to use SASS you'll need at least the sass-loader and the css-loader. The css-loader returns a JavaScript string. If you want to import the returned JavaScript string as StyleSheet, you'll also need the style-loader.

Run npm i sass-loader css-loader style-loader --save

Now you need to apply these loaders on all files that match /.scss$/:

// webpack.config.js
...
module: {
    loaders: [
        // the loaders will be applied from right to left
        { test: /.scss$/, loader: "style!css!sass" }
    ]
}
...

You can also pass options to node-sass as query parameters:

{
    test: /.scss$/, loader: "style!css!sass?includePaths[]=" + 
        path.resolve(__dirname, "./bower_components/bootstrap-sass/assets/stylesheets/"
}

Since bootstrap references icons via the url() statement, the css-loader will try to include these assets into the bundle and will throw an exception otherwise. That's why you'll also need the file-loader:

// webpack.config.js
...
module: {
    loaders: [
        { test: /.scss$/, loader: "style!css!sass" },
        { test: /.jpe?g$|.gif$|.png$|.svg$|.woff$|.ttf$/, loader: "file" },
    ]
}
...

Configure entry

To include bootstrap into your bundle there are several ways. One is via the multi-entry option as you've already tried. I recommend to use a single entry where you require() your main sass-file:

// main.js
require("./main.scss");

Given that your includePaths are configured then you can do:

// main.scss
// Set the font path so that url() points to the actual file
$icon-font-path: "../../../fonts/bootstrap";

@import "bootstrap";

Please note that import statements inside scss-files are not touched by webpack because libsass has no api (yet) to provide custom resolvers.

To prevent code duplication it's also important to have a single main sass-file, because webpack compiles every sass-file individually.

With the coffee-loader installed via npm your final webpack.config.js should look like:

module.exports = {
    entry: "./js/main.coffee",
    output: {
        path: __dirname,
        filename: "main.js"
    },
    module: {
        loaders: [
            { test: /.scss$/, loader: "style!css!sass" },
            { test: /.jpe?g$|.gif$|.png$|.svg$|.woff$|.ttf$/, loader: "file" },
            { test: /.coffee$/, loader: "coffee" }
        ]
    }
};

Webpack globally?

It's best not to install webpack globally, because it's a dependency of your project and thus should be controlled via npm. You can use the scripts-section of your package.json:

{
    ...
    "scripts": {
        "start": "webpack --config path/to/webpack.config.js & node server.js"
    }
}

Then you just need to run npm start


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...