2

Я пытаюсь сделать приложение React, которое я разрабатываю изоморфно. Один из known problems with doing this заключается в том, что загрузчики веб-пакетов допускают import/require активов, отличных от javascript, таких как файлы CSS. напримерСоздание серверной части (React) изоморфного webapp с webpack, включая загрузчик стиля для CSS

// ExampleComponent.jsx 
import Select from 'react-select'; 
import 'react-select/dist/react-select.css'; 

Если создание приложения с экспресс затем узел получит в этом импорт и не потому, что он не может обработать файл CSS, он ожидает Javascript только (и благодаря babel-register JSX).

Один из способов обойти это - использовать опцию target: 'node' в webpack при создании серверного приложения (которое включает в себя все общие части, такие как компоненты, поскольку это изоморфное приложение) для создания кода на стороне сервера. Это должно привести к созданию server.js, который затем может выполняться узлом.

. Примечание: Я знаю, что есть и другие способы вокруг этой конкретной задачи (например, не используя import/require, чтобы включать в себя все, что не является JavaScript, но это не практично на данном этапе развития в этом приложении

// webpack.config.js 
var webpack = require('webpack'); 
var path = require('path'); 

module.exports = [ 
    // Client build 
    { 
    entry: { 
     'bundle.min': [ 
     'bootstrap-webpack!./bootstrap.config.js', 
     'babel-polyfill', 
     './client/index.jsx' 
     ], 
     'bundle': [ 
     'bootstrap-webpack!./bootstrap.config.js', 
     'babel-polyfill', 
     './client/index.jsx' 
     ] 
    }, 
    output: { 
     path: './dist', 
     filename: '[name].js' 
    }, 
    plugins: [ 
     new webpack.optimize.UglifyJsPlugin({ 
     include: /\.min\.js$/, 
     minimize: true 
     }) 
    ], 
    module: { 
     loaders: [ 
     { 
      test: /\.jsx$/, 
      loader: 'babel-loader', 
      exclude: /node_modules/, 
      query: { 
      plugins: ['transform-runtime'], 
      presets: ['react', 'es2015', 'stage-0'] 
      } 
     }, 
     { 
      test: /\.js$/, 
      loader: 'babel-loader', 
      exclude: /node_modules/, 
      query: { 
      plugins: ['transform-runtime'], 
      presets: ['es2015', 'stage-0'] 
      } 
     }, 
     { 
      test: /\.css$/, 
      loader: 'style-loader!css-loader' 
     }, 
     { test: /\.png$/, 
      loader: "url-loader?limit=100000" 
     }, 

     // Bootstrap 
     { 
      test: /\.(woff|woff2)(\?v=\d+\.\d+\.\d+)?$/, 
      loader: 'url?limit=10000&mimetype=application/font-woff'}, 
     { 
      test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, 
      loader: 'url?limit=10000&mimetype=application/octet-stream' 
     }, 
     { 
      test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, 
      loader: 'file' 
     }, 
     { 
      test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, 
      loader: 'url?limit=10000&mimetype=image/svg+xml' 
     } 
     ] 
    }, 
    resolve: { 
     extensions: ['', '.js', '.jsx', '.json'] 
    } 
    }, 

    // Server build 
    { 
    entry: './server/server.jsx', 
    target: 'node', 
    node: { 
     console: false, 
     global: false, 
     process: false, 
     Buffer: false, 
     __filename: false, 
     __dirname: false, 
    }, 
    output: { 
     path: './dist', 
     filename: 'server.js', 
    }, 
    module: { 
     loaders: [ 
     { 
      test: /\.jsx$/, 
      loader: 'babel-loader', 
      exclude: /node_modules/, 
      query: { 
      plugins: ['transform-runtime'], 
      presets: ['react', 'es2015', 'stage-0'] 
      } 
     }, 
     { 
      test: /\.js$/, 
      loader: 'babel-loader', 
      exclude: /node_modules/, 
      query: { 
      plugins: ['transform-runtime'], 
      presets: ['es2015', 'stage-0'] 
      } 
     }, 
     { 
      test: /\.json$/, 
      loader: 'json-loader' 
     }, 
     { 
      test: /\.css$/, 
      loader: 'style-loader!css-loader' 
     }, 
     { test: /\.png$/, 
      loader: "url-loader?limit=100000" 
     }, 

     // Bootstrap 
     { 
      test: /\.(woff|woff2)(\?v=\d+\.\d+\.\d+)?$/, 
      loader: 'url?limit=10000&mimetype=application/font-woff'}, 
     { 
      test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, 
      loader: 'url?limit=10000&mimetype=application/octet-stream' 
     }, 
     { 
      test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, 
      loader: 'file' 
     }, 
     { 
      test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, 
      loader: 'url?limit=10000&mimetype=image/svg+xml' 
     } 
     ] 
    }, 
    resolve: { 
     extensions: ['', '.js', '.jsx', '.json'] 
    } 
    } 
]; 

проблема заключается в том, то, что стиль-погрузчик использует window, который, очевидно, не существует в среде узла.

$ node dist/server.js 
/Users/dpwrussell/Checkout/ExampleApp/dist/server.js:25925 
      return /msie [6-9]\b/.test(window.navigator.userAgent.toLowerCase()); 
            ^

ReferenceError: window is not defined 

от here в стиле погрузчиком.

Похоже, что я очень близок к тому, чтобы делать эту работу, поэтому любые мысли будут приветствоваться.

ответ

2

Ответ на вопрос: не использовать style-loader в вашей сборке сервера: его единственная цель - взять CSS, превратить его в элемент <style> и вставить его в DOM. Большинство людей, похоже, используют ExtractTextPlugin для сбора своих CSS для включения на стороне сервера.